diff --git a/include/ircd/ios.h b/include/ircd/ios.h index f9ae51043..dfb9214d7 100644 --- a/include/ircd/ios.h +++ b/include/ircd/ios.h @@ -108,7 +108,9 @@ struct ircd::ios::descriptor std::unique_ptr stats; std::function allocator; std::function deallocator; - bool continuation; + std::vector> history; // epoch, cycles + uint8_t history_pos {0}; + bool continuation {false}; descriptor(const string_view &name, const decltype(allocator) & = default_allocator, diff --git a/ircd/ios.cc b/ircd/ios.cc index 374ad3a19..a5448b094 100644 --- a/ircd/ios.cc +++ b/ircd/ios.cc @@ -100,6 +100,14 @@ ircd::ios::descriptor::descriptor(const string_view &name, { deallocator?: default_deallocator } +,history_pos +{ + 0 +} +,history +( + 256, {0} +) ,continuation { continuation @@ -169,6 +177,11 @@ ircd::ios::descriptor::stats::operator+=(const stats &o) // handler // +namespace ircd::ios +{ + constexpr bool profile_history {false}; +} + decltype(ircd::ios::handler::current) thread_local ircd::ios::handler::current; @@ -226,6 +239,14 @@ noexcept stats.slice_last = slice_stop - handler->ts; stats.slice_total += stats.slice_last; + if constexpr(profile_history) + { + assert(descriptor.history_pos < descriptor.history.size()); + descriptor.history[descriptor.history_pos][0] = handler::epoch; + descriptor.history[descriptor.history_pos][1] = stats.slice_last; + ++descriptor.history_pos; + } + assert(handler::current == handler); handler::current = nullptr; } @@ -236,14 +257,14 @@ ircd::ios::handler::enter(handler *const &handler) noexcept { assert(!handler::current); + handler::current = handler; + ++handler::epoch; + assert(handler && handler->descriptor); auto &descriptor(*handler->descriptor); assert(descriptor.stats); auto &stats(*descriptor.stats); - - handler::current = handler; - ++handler::epoch; ++stats.calls; const auto last_ts diff --git a/modules/console.cc b/modules/console.cc index 77b151774..3d32c5c22 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -1663,6 +1663,115 @@ console_cmd__ios(opt &out, const string_view &line) return true; } +bool +console_cmd__ios__record(opt &out, const string_view &line) +{ + std::map> map; + for(const auto *const &descriptor : ios::descriptor::list) + { + assert(descriptor); + const auto &d(*descriptor); + + const auto &history(d.history); + const auto &pos(d.history_pos); + + for(size_t i(pos); i < 256; ++i) + { + if(!history[i][0]) + continue; + + map.emplace(history[i][0], std::make_tuple(history[i][1], descriptor)); + } + + for(size_t i(0); i < pos; ++i) + { + if(!history[i][0]) + continue; + + map.emplace(history[i][0], std::make_tuple(history[i][1], descriptor)); + } + } + + uint64_t last(0); + for(const auto &[epoch, tuple] : map) + { + const auto &[cyc, desc] + { + tuple + }; + + const char ch + { + epoch == last + 1? '|': 'T' + }; + + out + << " " << ch + << std::right + << " " << std::setw(12) << epoch + << " " << std::setw(12) << cyc + << " " << std::left << std::setw(36) << desc->name; + + out + << std::endl; + + last = epoch; + } + + return true; +} + +bool +console_cmd__ios__history(opt &out, const string_view &line) +{ + for(const auto *const &descriptor : ios::descriptor::list) + { + assert(descriptor); + const auto &d(*descriptor); + + const auto &history(d.history); + const auto &pos(d.history_pos); + + out + << std::left << std::setw(3) << d.id + << " " << std::left << std::setw(48) << d.name + << std::endl; + + size_t k(0); + for(size_t i(pos); i < 256; ++i) + { + if(!history[i][0]) + continue; + + out + << "[" << std::right << std::setw(9) << history[i][0] + << " |" << std::right << std::setw(9) << history[i][1] + << "] "; + + if(++k % 12 == 0) + out << std::endl; + } + + for(size_t i(0); i < pos; ++i) + { + if(!history[i][0]) + continue; + + out + << "[" << std::right << std::setw(9) << history[i][0] + << " |" << std::right << std::setw(9) << history[i][1] + << "] "; + + if(++k % 12 == 0) + out << std::endl; + } + + out << std::endl; + } + + return true; +} + bool console_cmd__ios__depth(opt &out, const string_view &line) {