0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 07:23:53 +01:00

ircd::ctx: Improve prof related; add full ticker of counters.

This commit is contained in:
Jason Volk 2018-12-22 14:53:23 -08:00
parent 39d4f2fb83
commit d5ffc6b0de
4 changed files with 134 additions and 74 deletions

View file

@ -29,15 +29,22 @@
///
namespace ircd::ctx::prof
{
struct profile;
enum class event;
enum class event :uint8_t;
struct ticker;
// lowlevel
// util
ulong rdtsc();
string_view reflect(const event &);
// state accessors
const ulong &total_slice_cycles();
const ulong &total_slices();
// totals
const ticker &get();
const uint64_t &get(const event &);
// specific context
const ticker &get(const ctx &c);
const uint64_t &get(const ctx &c, const event &);
// current slice state
const ulong &cur_slice_start();
ulong cur_slice_cycles();
@ -52,22 +59,6 @@ namespace ircd::ctx::prof
void mark(const event &);
}
/// Profiling events for marking. These are currently used internally at the
/// appropriate point to mark(): the user of ircd::ctx has no reason to mark()
/// these events; this interface is not quite developed for general use yet.
enum class ircd::ctx::prof::event
{
SPAWN, // Context spawn requested
JOIN, // Context join requested
JOINED, // Context join completed
CUR_ENTER, // Current context entered
CUR_LEAVE, // Current context leaving
CUR_YIELD, // Current context yielding
CUR_CONTINUE, // Current context continuing
CUR_INTERRUPT, // Current context detects interruption
CUR_TERMINATE, // Current context detects termination
};
namespace ircd::ctx::prof::settings
{
extern conf::item<double> stack_usage_warning; // percentage
@ -78,9 +69,31 @@ namespace ircd::ctx::prof::settings
extern conf::item<ulong> slice_assertion; // abort() when exceeded (not a signal, must yield)
}
/// structure aggregating any profiling related state for a ctx
struct ircd::ctx::prof::profile
/// Profiling events for marking. These are currently used internally at the
/// appropriate point to mark(): the user of ircd::ctx has no reason to mark()
/// these events; this interface is not quite developed for general use yet.
enum class ircd::ctx::prof::event
:uint8_t
{
ulong cycles {0}; // monotonic counter (rdtsc)
uint64_t yields {0}; // monotonic counter
SPAWN, // Context spawn requested
JOIN, // Context join requested
JOINED, // Context join completed
ENTER, // Current context entered
LEAVE, // Current context leaving
YIELD, // Current context yielding
CONTINUE, // Current context continuing
INTERRUPT, // Current context detects interruption
TERMINATE, // Current context detects termination
_NUM_
};
/// structure aggregating any profiling related state for a ctx
struct ircd::ctx::prof::ticker
{
// monotonic counter (rdtsc)
ulong cycles {0};
// monotonic counters for events
std::array<uint64_t, num_of<prof::event>()> event {{0}};
};

View file

@ -85,10 +85,10 @@ noexcept try
this->yc = &yc;
notes = 1;
stack.base = uintptr_t(__builtin_frame_address(0));
mark(prof::event::CUR_ENTER);
mark(prof::event::ENTER);
const unwind atexit([this]
{
mark(prof::event::CUR_LEAVE);
mark(prof::event::LEAVE);
adjoindre.notify_all();
this->yc = nullptr;
ircd::ctx::current = nullptr;
@ -279,7 +279,7 @@ ircd::ctx::ctx::termination_point(std::nothrow_t)
{
assert(~flags & context::NOINTERRUPT);
flags |= context::NOINTERRUPT;
mark(prof::event::CUR_TERMINATE);
mark(prof::event::TERMINATE);
return true;
}
else return false;
@ -294,7 +294,7 @@ ircd::ctx::ctx::interruption_point(std::nothrow_t)
{
assert(~flags & context::NOINTERRUPT);
flags &= ~context::INTERRUPTED;
mark(prof::event::CUR_INTERRUPT);
mark(prof::event::INTERRUPT);
return true;
}
else return false;
@ -490,7 +490,7 @@ ircd::ctx::cycles(const ctx &ctx)
const uint64_t &
ircd::ctx::yields(const ctx &ctx)
{
return ctx.profile.yields;
return prof::get(ctx, prof::event::YIELD);
}
/// Returns the notification count for `ctx`
@ -962,7 +962,7 @@ ircd::ctx::continuation::continuation(const predicate &pred,
// Tell the profiler this is the point where the context has concluded
// its execution run and is now yielding.
mark(prof::event::CUR_YIELD);
mark(prof::event::YIELD);
// Null the fundamental current context register as the last operation
// during execution before yielding. When a context resumes it will
@ -980,7 +980,7 @@ noexcept(false)
// Tell the profiler this is the point where the context is now resuming.
// On some optimized builds this might lead nowhere.
mark(prof::event::CUR_CONTINUE);
mark(prof::event::CONTINUE);
// Unconditionally reset the notes counter to 1 because we're awake now.
self->notes = 1;
@ -1377,20 +1377,21 @@ ircd::ctx::debug_stats(const pool &pool)
namespace ircd::ctx::prof
{
ulong _slice_start; // Current/last time slice started
ulong _slice_stop; // Last time slice ended
profile _total; // Totals counter for all contexts.
ulong _slice_start; // Current/last time slice started
ulong _slice_stop; // Last time slice ended
ticker _total; // Totals kept for all contexts.
void check_stack();
void check_slice();
static void check_stack();
static void check_slice();
static void slice_enter();
static void slice_leave();
void slice_enter();
void slice_leave();
static void handle_cur_continue();
static void handle_cur_yield();
static void handle_cur_leave();
static void handle_cur_enter();
void handle_cur_continue();
void handle_cur_yield();
void handle_cur_leave();
void handle_cur_enter();
static void inc_ticker(const event &e);
}
// stack_usage_warning at 1/3 engineering tolerance
@ -1439,44 +1440,35 @@ ircd::ctx::prof::settings::slice_assertion
void
ircd::ctx::prof::mark(const event &e)
{
inc_ticker(e);
switch(e)
{
case event::CUR_ENTER: handle_cur_enter(); break;
case event::CUR_LEAVE: handle_cur_leave(); break;
case event::CUR_YIELD: handle_cur_yield(); break;
case event::CUR_CONTINUE: handle_cur_continue(); break;
default: break;
case event::ENTER: handle_cur_enter(); break;
case event::LEAVE: handle_cur_leave(); break;
case event::YIELD: handle_cur_yield(); break;
case event::CONTINUE: handle_cur_continue(); break;
default: break;
}
}
#else
void
ircd::ctx::prof::mark(const event &e)
ircd::ctx::prof::mark(const event &)
{
}
#endif
ulong
ircd::ctx::prof::cur_slice_cycles()
void
ircd::ctx::prof::inc_ticker(const event &e)
{
return rdtsc() - cur_slice_start();
}
assert(uint8_t(e) < num_of<event>());
const ulong &
ircd::ctx::prof::cur_slice_start()
{
return _slice_start;
}
// Increment the ticker for all contexts.
_total.event[uint8_t(e)]++;
const ulong &
ircd::ctx::prof::total_slice_cycles()
{
return _total.cycles;
}
const ulong &
ircd::ctx::prof::total_slices()
{
return _total.yields;
// Increment the ticker for the context's instance
if(likely(current))
current->profile.event[uint8_t(e)]++;
}
void
@ -1522,9 +1514,7 @@ ircd::ctx::prof::slice_leave()
const auto last_slice(_slice_stop - _slice_start);
c.stack.at = stack_at_here();
c.profile.cycles += last_slice;
c.profile.yields++;
_total.cycles += last_slice;
_total.yields++;
}
void
@ -1642,6 +1632,63 @@ ircd::ctx::prof::slice_exceeded_warning(const ulong &cycles)
return threshold > 0 && cycles >= threshold;
}
ulong
ircd::ctx::prof::cur_slice_cycles()
{
return rdtsc() - cur_slice_start();
}
const ulong &
ircd::ctx::prof::cur_slice_start()
{
return _slice_start;
}
const uint64_t &
ircd::ctx::prof::get(const ctx &c,
const event &e)
{
return get(c).event.at(uint8_t(e));
}
const ircd::ctx::prof::ticker &
ircd::ctx::prof::get(const ctx &c)
{
return c.profile;
}
const uint64_t &
ircd::ctx::prof::get(const event &e)
{
return get().event.at(uint8_t(e));
}
const ircd::ctx::prof::ticker &
ircd::ctx::prof::get()
{
return _total;
}
ircd::string_view
ircd::ctx::prof::reflect(const event &e)
{
switch(e)
{
case event::SPAWN: return "SPAWN";
case event::JOIN: return "JOIN";
case event::JOINED: return "JOINED";
case event::ENTER: return "ENTER";
case event::LEAVE: return "LEAVE";
case event::YIELD: return "YIELD";
case event::CONTINUE: return "CONTINUE";
case event::INTERRUPT: return "INTERRUPT";
case event::TERMINATE: return "TERMINATE";
case event::_NUM_: break;
}
return "?????";
}
#ifdef HAVE_X86INTRIN_H
ulong
ircd::ctx::prof::rdtsc()

View file

@ -43,9 +43,9 @@ struct ircd::ctx::ctx
boost::asio::steady_timer alarm; // acting semaphore (64B)
boost::asio::yield_context *yc {nullptr}; // boost interface
continuation *cont {nullptr}; // valid when asleep; invalid when awake
ircd::ctx::stack stack; // stack related structure
prof::profile profile; // prof related structure
list::node node; // node for ctx::list
ircd::ctx::stack stack; // stack related structure
prof::ticker profile; // prof related structure
dock adjoindre; // contexts waiting for this to join()
bool started() const; // context was ever entered

View file

@ -1345,7 +1345,7 @@ console_cmd__ctx__list(opt &out, const string_view &line)
<< std::setw(15) << std::right << cycles(ctx)
<< " ";
const long double total_cyc(ctx::prof::total_slice_cycles());
const long double total_cyc(ctx::prof::get().cycles);
const auto tsc_pct
{
total_cyc > 0.0? (cycles(ctx) / total_cyc) : 0.0L