20#include <boost/algorithm/string.hpp>
31 size_t max_n_checkpoints) :
33 m_name(std::move(name_moved)),
34 m_which_clocks(which_clocks)
38 using boost::algorithm::join;
42 assert(max_n_checkpoints != 0);
48 vector<string> active_clock_type_strs;
50 for (
size_t clock_type_idx = 0; clock_type_idx !=
m_which_clocks.size(); ++clock_type_idx)
59 "active clock types = [" << join(active_clock_type_strs,
" | ") <<
"].");
70 m_name(std::move(name_moved)),
71 m_which_clocks(which_clocks)
123 scaled_since_start *= mult_scale;
124 scaled_since_start /= div_scale;
133 using ::clock_gettime;
135 using ::CLOCK_PROCESS_CPUTIME_ID;
137 using boost::chrono::duration;
138 using boost::chrono::nanoseconds;
145 return Fine_clock::now();
159 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time_spec);
173 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time_spec);
181 assert(
false &&
"END_SENTINEL passed to now() -- must specify actual Clock_type.");
185 assert(
false &&
"Bug? now() forgot to handle a Clock_type, yet compiler did not warn in switch()?");
203 if (do_cpu_user_lo || do_cpu_sys_lo)
249 return Cpu_split_clock::now().time_since_epoch().count();
255 using boost::chrono::nanoseconds;
262 using Cpu_split_component_duration = boost::chrono::duration<nanoseconds::rep, Cpu_split_clock::period>;
268 return Time_pt(
Duration(Cpu_split_component_duration(user_else_sys ? cpu_combo_now_raw.user
269 : cpu_combo_now_raw.system)));
277 const auto checkpoint_when =
now();
311 "--- Timer [" <<
m_name <<
"] ----\n"
317 (*os) <<
" [#" << idx <<
"| " <<
checkpoint <<
']';
349 std::string&& name_moved,
size_t max_n_samples) :
351 m_name(std::move(name_moved))
353 assert(max_n_samples != 0);
359 assert((m_timers.size() + 1) <= m_timers.capacity());
360 m_timers.push_back(timer_ptr);
362 FLOW_LOG_TRACE(
"Aggregator [" <<
m_name <<
"]: Added Timer # [" << (m_timers.size() - 1) <<
"] "
363 "named [" << timer_ptr->m_name <<
"].");
372 (
log::Logger* alternate_logger_ptr_or_null,
bool info_log_result,
373 uint64_t mean_scale_or_zero)
const
378 assert(!m_timers.empty());
379 auto model_timer = m_timers.front();
383 agg_timer->m_checkpoints.reserve(model_timer->m_checkpoints.size());
386 bool first_dur =
true;
390 for (
const auto& timer : m_timers)
392 if (timer != model_timer)
394 assert(timer->m_which_clocks == model_timer->m_which_clocks);
395 assert(timer->m_checkpoints.size() == model_timer->m_checkpoints.size());
398 size_t idx_checkpoints = 0;
399 for (
const auto&
checkpoint : timer->m_checkpoints)
401 if (timer == model_timer)
404 agg_timer->m_checkpoints.push_back(
checkpoint);
410 const auto& model_checkpoint = model_timer->m_checkpoints[idx_checkpoints];
437 agg_timer->m_last_checkpoint_when = agg_timer->m_start_when;
438 agg_timer->m_last_checkpoint_when += total_dur;
440 assert(agg_timer->since_start().m_values == total_dur.
m_values);
442 const auto n_samples = m_timers.size();
443 const bool mean_aggregation = mean_scale_or_zero != 0;
445 if (mean_aggregation)
448 "with [" << n_samples <<
"] samples "
449 "scaled by [" << mean_scale_or_zero <<
"] samples.");
450 agg_timer->scale(mean_scale_or_zero, n_samples);
455 "with [" << n_samples <<
"] samples.");
463 log_aggregated_result_in_timer(alternate_logger_ptr_or_null ? alternate_logger_ptr_or_null :
get_logger(),
464 *agg_timer, n_samples, mean_scale_or_zero);
473 uint64_t mean_scale_or_zero)
479 const bool mean_aggregation = mean_scale_or_zero != 0;
482 if (!mean_aggregation)
485 "Collated timing result from [" << n_samples <<
"] samples: "
486 "SUM: [\n" << agg_timer <<
"\n].");
490 if (mean_scale_or_zero == 1)
493 "Collated timing result from [" << n_samples <<
"] samples: "
494 "MEAN: [\n" << agg_timer <<
"\n].");
498 assert(mean_scale_or_zero != 1);
500 "Collated timing result from [" << n_samples <<
"] samples: "
501 "SCALED-MEAN per [" << mean_scale_or_zero <<
"] samples: [\n" << agg_timer <<
"\n].");
507 bool show_sum,
bool show_mean,
508 uint64_t mean_scale_or_zero)
const
510 FLOW_LOG_INFO(
"Aggregation completed earlier. Collating aggregated timing data; logging here/elsewhere:");
514 if ((mean_scale_or_zero == 1) && show_mean)
519 mean_scale_or_zero = 0;
525 create_aggregated_result(alternate_logger_ptr_or_null,
true, 0);
529 create_aggregated_result(alternate_logger_ptr_or_null,
true, 1);
531 if (mean_scale_or_zero != 0)
533 create_aggregated_result(alternate_logger_ptr_or_null,
true, mean_scale_or_zero);
const Component & get_log_component() const
Returns reference to the stored Component object, particularly as many FLOW_LOG_*() macros expect.
Logger * get_logger() const
Returns the stored Logger pointer, particularly as many FLOW_LOG_*() macros expect.
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
virtual bool should_log(Sev sev, const Component &component) const =0
Given attributes of a hypothetical message that would be logged, return true if that message should b...
void aggregate(Checkpointing_timer_ptr timer_ptr)
Register given Checkpointing_timer for aggregated results.
void log_aggregated_results(log::Logger *alternate_logger_ptr_or_null, bool show_sum, bool show_mean, uint64_t mean_scale_or_zero) const
Called after the final Checkpointing_timer has finished (final checkpoint() call) and been aggregate(...
static void log_aggregated_result_in_timer(log::Logger *logger_ptr, const Checkpointing_timer &agg_timer, unsigned int n_samples, uint64_t mean_scale_or_zero=1)
Given an aggregated-result Checkpointing_timer (as if returned by create_aggregated_result()) logs th...
Checkpointing_timer_ptr create_aggregated_result(log::Logger *alternate_logger_ptr_or_null, bool info_log_result, uint64_t mean_scale_or_zero=1) const
Provides programmatic access to the aggregation result that would be logged by log_aggregated_results...
Aggregator(log::Logger *logger_ptr, std::string &&name_moved, size_t max_n_samples)
Constructs a new, empty aggregator.
void clear()
Act as if aggregate() has never been called since construction.
std::vector< Checkpointing_timer_ptr > m_timers
The ref-counted pointers to source timers passed to aggregate() in that order.
The central class in the perf Flow module, this efficiently times the user's operation,...
void output(std::ostream *os) const
Equivalent to (*os) << (*this).
const std::vector< Checkpoint > & checkpoints() const
Returns the checkpoints recorded so far.
const std::string m_name
The immutable human-readable name for this timer. It's const so no need for accessor for now.
static Clock_types_subset process_cpu_clock_types()
Returns the bit-set containing only those Clock_types enabled that measure passage of processor time ...
void scale(uint64_t mult_scale, uint64_t div_scale)
Called anytime after the last checkpoint(), this modifies the data collected so far to be as if every...
Time_pt_set now() const
Sample all currently enabled Clock_types' clocks and return those values, each of which is a time sta...
Time_pt_set m_last_checkpoint_when
The value of now() recorded during the last checkpoint() call; or equals m_start_when if checkpoint()...
static Cpu_split_clock_durs_since_epoch now_cpu_lo_res_raw()
Returns the current Cpu_split_clock time, essentially as a combo struct containing raw (integer) coun...
static Time_pt now_cpu_lo_res(const Cpu_split_clock_durs_since_epoch &cpu_combo_now_raw, bool user_else_sys)
Returns individual Time_pt value returnable by now() various overloads: either the user time or syste...
static Clock_types_subset real_clock_types()
Returns the bit-set containing only those Clock_types enabled that measure passage of real (wall cloc...
std::vector< Checkpoint > m_checkpoints
The checkpoints recorded so far, in order, one per checkpoint() call.
const Checkpoint & checkpoint(std::string &&name_moved)
Records a checkpoint, which takes a sample of all enabled Clock_types' clocks and records the corresp...
Checkpointing_timer(log::Logger *logger_ptr, std::string &&name_moved, Clock_types_subset which_clocks, size_t max_n_checkpoints)
Constructs a new timer and immediately begins measuring time, in that the next checkpoint() call will...
static Clock_types_subset thread_cpu_clock_types()
Returns the bit-set containing only those Clock_types enabled that measure passage of processor time ...
Time_pt_set m_start_when
The value of now() saved in public constructor, marking the time point when the timing began.
const Clock_types_subset m_which_clocks
The bit-set indexed by size_t(Clock_type::...) wherein that clock will be sampled in now() and checkp...
Cpu_split_clock::times Cpu_split_clock_durs_since_epoch
Short-hand for the combo (user/kernel) durations-since-epoch tracked by Cpu_split_clock.
Duration_set since_start() const
Returns the duration(s) (for all enabled Clock_types) between construction and the last checkpoint() ...
#define FLOW_LOG_INFO(ARG_stream_fragment)
Logs an INFO message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
#define FLOW_LOG_TRACE_WITHOUT_CHECKING(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
#define FLOW_LOG_SET_CONTEXT(ARG_logger_ptr, ARG_component_payload)
For the rest of the block within which this macro is instantiated, causes all FLOW_LOG_....
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
@ S_TRACE
Message indicates any condition that may occur with great frequency (thus verbose if logged).
Flow module containing tools for profiling and optimization.
boost::shared_ptr< Checkpointing_timer > Checkpointing_timer_ptr
Short-hand for ref-counting pointer to Checkpointing_timer.
Fine_duration Duration
Short-hand for a high-precision boost.chrono duration, formally equivalent to flow::Fine_duration.
std::ostream & operator<<(std::ostream &os, const Checkpointing_timer::Checkpoint &checkpoint)
Prints string representation of the given Checkpoint to the given ostream.
Duration::rep duration_rep_t
The raw type used in Duration to store its clock ticks.
std::bitset< size_t(Clock_type::S_END_SENTINEL)> Clock_types_subset
Short-hand for a bit-set of N bits which represents the presence or absence of each of the N possible...
Fine_time_pt Time_pt
Short-hand for a high-precision boost.chrono point in time, formally equivalent to flow::Fine_time_pt...
Clock_type
Clock types supported by flow::perf module facilities, perf::Checkpointing_timer in particular.
@ S_CPU_SYS_LO_RES
Counterpart of S_CPU_USER_LO_RES, measuring processor time (kernel-level) spent by the current proces...
@ S_END_SENTINEL
Final, invalid clock type; its numerical value equals the number of clocks currently supported.
@ S_REAL_HI_RES
Measures real time (not processor time), using the highest-resolution system clock available that gua...
@ S_CPU_THREAD_TOTAL_HI_RES
Similar to S_CPU_TOTAL_HI_RES but applied to the calling thread as opposed to entire process.
@ S_CPU_TOTAL_HI_RES
Measures processor time (user- and kernel-level total) spent by the current process; this is the high...
@ S_CPU_USER_LO_RES
Along with S_CPU_SYS_LO_RES, measures processor time (user-level) spent by the current process; this ...
std::string ostream_op_string(T const &... ostream_args)
Equivalent to ostream_op_to_string() but returns a new string by value instead of writing to the call...
Flow_log_component
The flow::log::Component payload enumeration comprising various log components used by Flow's own int...
The entirety of the information recorded with each Checkpointing_timer::checkpoint() call; it contain...
const std::string m_name
User-supplied name of the checkpoint.
Duration_set m_since_last
For the T.checkpoint() call that generated *this, for each enabled Clock_type: Time elapsed since eit...
Convenience wrapper around an array<Duration, N>, which stores a duration for each of the N possible ...
std::array< Duration, size_t(Clock_type::S_END_SENTINEL)> m_values
The underlying data, directly readable and writable by user. NOT ZERO-INITIALIZED ON CONSTRUCTION (or...
Convenience wrapper around an array<Time_pt, N>, which stores a time point for each of the N possible...
std::array< Time_pt, size_t(Clock_type::S_END_SENTINEL)> m_values
The underlying data, directly readable and writable by user. NOT ZERO-INITIALIZED ON CONSTRUCTION (or...