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.emplace_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.emplace_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...