CUBRID Engine  latest
perf.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * perf.hpp - interface for performance statistics basic utilities
21  */
22 
23 #ifndef _PERF_HPP_
24 #define _PERF_HPP_
25 
26 #include "perf_def.hpp"
27 
28 #include <string>
29 #include <type_traits>
30 
31 #include <cassert>
32 
33 // cubperf basic functionality
34 //
35 // description:
36 //
37 // the purpose of this module is to offer consistent ways of collecting statistics atomically and non-atomically.
38 // it provides an interface to:
39 // 1. declare multiple different statistics in a group
40 // 2. create sets of atomic or non-atomic values for this group of statistics
41 // 3. safely manipulate the set of values
42 // 4. easily modify the group of statistics by adding, removing or changing types of statistics
43 //
44 // the model is somewhat inspired from performance monitor's PSTAT_METADATA and the way it collects statistics,
45 // with the addition C++ templates
46 // templates are used for:
47 // 1. avoiding duplicate implementation for atomic and non-atomic statistics sets.
48 // 2. automatic timer statistics conversions
49 //
50 // usage:
51 //
52 // // define statistics ID's; we want these const to let compiler replace them
53 // // note - stat_defition will check provided id's are successive starting with 0
54 // static const cubperf::stat_id STAT_COUNTER = 0;
55 // static const cubperf::stat_id STAT_TIMER = 1;
56 // static const cubperf::stat_id STAT_COUNTER_AND_TIMER = 2;
57 // // define your set of statistics:
58 // static const cubperf::stat_definition Mystat_definition =
59 // {
60 // cubperf::stat_definition (STAT_COUNTER, cubperf::stat_definition::COUNTER, "c_counter"),
61 // cubperf::stat_definition (STAT_TIMER, cubperf::stat_definition::TIMER, "t_timer"),
62 // cubperf::stat_definition (STAT_COUNTER_AND_TIMER, cubperf::stat_definition::COUNTER_AND_TIMER, "ct_counter"
63 // "ct_timer")
64 // };
65 //
66 // // a statistics set of values can be created using definition
67 // cubperf::statset& my_statset = Mystat_definition.create_statset ();
68 // // an atomic set can be created with same definition
69 // cubperf::atomic_statset& my_atomic_statset = Mystat_definition.create_atomic_statset ();
70 //
71 // // collecting statistics is supervised by definition
72 // Mystat_definition.increment (my_statset, STAT_COUNTER, 10); // a counter is expected
73 //
74 // // same for atomic sets
75 // Mystat_definition.time_and_increment (my_atomic_statset, STAT_COUNTER_AND_TIMER); // a counter and timer expected
76 // // note: by default counter is incremented by 1;
77 // // by default timer is incremented by duration since last time_and_increment
78 //
79 // // print statistics
80 // stat_value *values = new stat_value [Mystat_definition.get_value_count ()]; // allocate array to copy values to
81 // // just for example
82 // // get statistics; timers can be automatically converted to desired unit
83 // Mystat_definition.get_stat_values_with_converted_timers<std::chrono::milliseconds> (my_atomic_statset, values);
84 //
85 // // print all values
86 // for (std::size_t index = 0; index < Mystat_definition.get_value_count (); index++)
87 // {
88 // printf ("%s = %llu\n", Mystat_definition.get_value_name (index), values[index]);
89 // }
90 //
91 // // note - to extend the statistics set, you only need to:
92 // // 1. add new ID.
93 // // 2. update Mystat_definition
94 // // 3. call increment/time/time_and_increment operations on new statistic
95 //
96 // delete values;
97 // delete &my_statset;
98 // delete &my_atomic_statset
99 //
100 
101 namespace cubperf
102 {
103  // stat_definition - defines one statistics entry in a set
105  {
106  public:
107 
108  // possible types
109  enum type
110  {
114  };
115 
116  // constructor
117  stat_definition (const stat_id id, type stat_type, const char *first_name, const char *second_name = NULL);
118  // copy constructor
119  stat_definition (const stat_definition &other);
120 
122 
123  std::size_t get_value_count (void) const; // get value count
124 
125  private:
126  friend class statset_definition; // statset_definition will process private content
127 
128  stat_definition (void);
129 
130  // make sure this is updated if more values are possible
131  static const std::size_t MAX_VALUE_COUNT = 2;
132 
133  stat_id m_id; // assigned ID
134  type m_type; // type
135  const char *m_names[MAX_VALUE_COUNT]; // one per each value
136  std::size_t m_offset; // used by stat_definition to track each statistic's values
137  };
138 
139  // statset_definition - defines a set of statistics and supervises all operations on sets of values
140  //
141  // see how to use in file description comment
142  //
144  {
145  public:
146  // no default constructor
147  statset_definition (void) = delete;
148  statset_definition (std::initializer_list<stat_definition> defs);
149  ~statset_definition (void);
150 
151  // create (construct) a non-atomic set of values
152  statset *create_statset (void) const;
153  // create (construct) an atomic set of values
154  atomic_statset *create_atomic_statset (void) const;
155 
156  // increment counter statistic
157  inline void increment (statset &statsetr, stat_id id, stat_value incr = 1) const;
158  inline void increment (atomic_statset &statsetr, stat_id id, stat_value incr = 1) const;
159 
160  // register time durations to timer statistic
161  // 1. with duration argument, adds the duration to timer statistic.
162  // 2. without duration argument, uses statset internal time point; adds duration betweem time point and now
163  // and resets the time point to now.
164  inline void time (statset &statsetr, stat_id id, duration d) const;
165  inline void time (statset &statsetr, stat_id id) const;
166  inline void time (atomic_statset &statsetr, stat_id id, duration d) const;
167  inline void time (atomic_statset &statsetr, stat_id id) const;
168 
169  // update counter and timer statistic. equivalent to time + increment functions.
170  // timer is first to allow default counter value of 1
171  inline void time_and_increment (statset &statsetr, stat_id id, duration d, stat_value incr = 1) const;
172  inline void time_and_increment (statset &statsetr, stat_id id, stat_value incr = 1) const;
173  inline void time_and_increment (atomic_statset &statsetr, stat_id id, duration d, stat_value incr = 1) const;
174  inline void time_and_increment (atomic_statset &statsetr, stat_id id, stat_value incr = 1) const;
175 
176  // copy from set of values to given array
177  void get_stat_values (const statset &statsetr, stat_value *output_stats) const;
178  void get_stat_values (const atomic_statset &statsetr, stat_value *output_stats) const;
179  // accumulate values from set of values to given array
180  void add_stat_values (const statset &statsetr, stat_value *output_stats) const;
181  void add_stat_values (const atomic_statset &statsetr, stat_value *output_stats) const;
182 
183  // copy values from set of values to given array by converting timer values to desired duration type
184  template <typename Duration>
185  void get_stat_values_with_converted_timers (const statset &statsetr, stat_value *output_stats) const;
186  template <typename Duration>
187  void get_stat_values_with_converted_timers (const atomic_statset &statsetr, stat_value *output_stats) const;
188  // accumulate values from set of values to given array by converting timer values to desired duration type
189  template <typename Duration>
190  void add_stat_values_with_converted_timers (const statset &statsetr, stat_value *output_stats) const;
191  template <typename Duration>
192  void add_stat_values_with_converted_timers (const atomic_statset &statsetr, stat_value *output_stats) const;
193 
194  // getters
195  std::size_t get_stat_count () const; // statistics (counter, timer, counter and timer) count
196  std::size_t get_value_count () const; // value count (size of set of values)
197  const char *get_value_name (std::size_t value_index) const; // get the name for value at index
198  std::size_t get_values_memsize (void) const; // get memory size for set of values
199 
200  private:
201 
202  // generic versions of statistics operation on set of values
203  // common point for specialized versions of operations - on statset and atomic_statset
204  template <bool IsAtomic>
205  inline void generic_increment (generic_statset<IsAtomic> &statsetr, stat_id id, stat_value incr) const;
206  template <bool IsAtomic>
207  inline void generic_time (generic_statset<IsAtomic> &statsetr, stat_id id, duration d) const;
208  template <bool IsAtomic>
209  inline void generic_time (generic_statset<IsAtomic> &statsetr, stat_id id) const;
210  template <bool IsAtomic>
211  inline void generic_time_and_increment (generic_statset<IsAtomic> &statsetr, stat_id id, stat_value incr,
212  duration d) const;
213  template <bool IsAtomic>
214  inline void generic_time_and_increment (generic_statset<IsAtomic> &statsetr, stat_id id, stat_value incr) const;
215 
216  // functions used for time conversions
217  // convert time value from default (nanosecs) to desired duration type
218  template <typename Duration>
219  stat_value convert_timeval (stat_value nanosecs) const;
220  // generic function to copy statistics into array of values
221  template <bool IsAtomic, typename Duration>
222  void generic_get_stat_values_with_converted_timers (const generic_statset<IsAtomic> &statsetr,
223  stat_value *output_stats) const;
224  // generic function to accumulate statistics into array of values
225  template <bool IsAtomic, typename Duration>
226  void generic_add_stat_values_with_converted_timers (const generic_statset<IsAtomic> &statsetr,
227  stat_value *output_stats) const;
228 
229  std::size_t m_stat_count;
230  std::size_t m_value_count;
231  stat_definition *m_stat_defs; // vector with statistics definitions
232  std::string *m_value_names; // vector with names for each value in the set
233  };
234 
236  // functions
238 
239  inline void reset_timept (time_point &timept);
240 
242  // Template & inline implementations
244 
246  // statset_definition
248 
249  template <bool IsAtomic>
250  void
252  {
253  assert (id < get_stat_count ());
254  assert (m_stat_defs[id].m_type == stat_definition::type::COUNTER);
255 
256  // increment at id's offset
257  statsetr.m_values[m_stat_defs[id].m_offset] += incr;
258  }
259 
260  void
261  statset_definition::increment (statset &statsetr, stat_id id, stat_value incr /* = 1 */) const
262  {
263  generic_increment<false> (statsetr, id, incr);
264  }
265 
266  void
267  statset_definition::increment (atomic_statset &statsetr, stat_id id, stat_value incr /* = 1 */) const
268  {
269  generic_increment<true> (statsetr, id, incr);
270  }
271 
272  template <bool IsAtomic>
273  void
275  {
276  assert (id < get_stat_count ());
277  assert (m_stat_defs[id].m_type == stat_definition::type::TIMER);
278 
279  // add duration at id's offset
280  statsetr.m_values[m_stat_defs[id].m_offset] += d.count ();
281  }
282 
283  template <bool IsAtomic>
284  void
286  {
287  time_point nowpt = clock::now ();
288  generic_time (statsetr, id, nowpt - statsetr.m_timept);
289  statsetr.m_timept = nowpt;
290  }
291 
292  void
294  {
295  generic_time<false> (statsetr, id, d);
296  }
297 
298  void
300  {
301  generic_time<false> (statsetr, id);
302  }
303 
304  void
306  {
307  generic_time<true> (statsetr, id, d);
308  }
309 
310  void
312  {
313  generic_time<true> (statsetr, id);
314  }
315 
316  template <bool IsAtomic>
317  void
319  duration d) const
320  {
321  assert (id < get_stat_count ());
322  assert (m_stat_defs[id].m_type == stat_definition::type::COUNTER_AND_TIMER);
323 
324  // add duration at id's offset
325  std::size_t offset = m_stat_defs[id].m_offset;
326  statsetr.m_values[offset] += incr; // first is counter
327  statsetr.m_values[offset + 1] += d.count (); // then is timer
328  }
329 
330  template <bool IsAtomic>
331  void
333  {
334  time_point nowpt = clock::now ();
335  generic_time_and_increment (statsetr, id, incr, nowpt - statsetr.m_timept);
336  statsetr.m_timept = nowpt;
337  }
338 
339  void
341  {
342  generic_time_and_increment<false> (statsetr, id, incr, d);
343  }
344 
345  void
346  statset_definition::time_and_increment (statset &statsetr, stat_id id, stat_value incr /* = 1 */) const
347  {
348  generic_time_and_increment<false> (statsetr, id, incr);
349  }
350 
351  void
353  stat_value incr /* = 1 */) const
354  {
355  generic_time_and_increment<true> (statsetr, id, incr, d);
356  }
357 
358  void
360  {
361  generic_time_and_increment<true> (statsetr, id, incr);
362  }
363 
364  template <typename Duration>
365  stat_value
366  statset_definition::convert_timeval (stat_value default_duration_count) const
367  {
368  duration default_duration (default_duration_count);
369  Duration desired_duration = std::chrono::duration_cast<Duration> (default_duration);
370  return desired_duration.count ();
371  }
372 
373  template <bool IsAtomic, typename Duration>
374  void
376  stat_value *output_stats) const
377  {
378  std::size_t offset = 0;
379  for (stat_id id = 0; id < get_stat_count (); id++)
380  {
381  offset = m_stat_defs[id].m_offset;
382  switch (m_stat_defs[id].m_type)
383  {
385  output_stats[offset] = statsetr.m_values[offset];
386  break;
388  output_stats[offset] = convert_timeval<Duration> (statsetr.m_values[offset]);
389  break;
391  output_stats[offset] = statsetr.m_values[offset];
392  output_stats[offset + 1] = convert_timeval<Duration> (statsetr.m_values[offset + 1]);
393  break;
394  default:
395  assert (false);
396  break;
397  }
398  }
399  }
400 
401  template <typename Duration>
402  void
404  {
405  return generic_get_stat_values_with_converted_timers<false, Duration> (statsetr, output_stats);
406  }
407 
408  template <typename Duration>
409  void
411  stat_value *output_stats) const
412  {
413  return generic_get_stat_values_with_converted_timers<true, Duration> (statsetr, output_stats);
414  }
415 
416  template <bool IsAtomic, typename Duration>
417  void
419  stat_value *output_stats) const
420  {
421  std::size_t offset = 0;
422  for (stat_id id = 0; id < get_stat_count (); id++)
423  {
424  offset = m_stat_defs[id].m_offset;
425  switch (m_stat_defs[id].m_type)
426  {
428  output_stats[offset] += statsetr.m_values[offset];
429  break;
431  output_stats[offset] += convert_timeval<Duration> (statsetr.m_values[offset]);
432  break;
434  output_stats[offset] += statsetr.m_values[offset];
435  output_stats[offset + 1] += convert_timeval<Duration> (statsetr.m_values[offset + 1]);
436  break;
437  default:
438  assert (false);
439  break;
440  }
441  }
442  }
443 
444  template <typename Duration>
445  void
447  {
448  return generic_add_stat_values_with_converted_timers<false, Duration> (statsetr, output_stats);
449  }
450 
451  template <typename Duration>
452  void
454  stat_value *output_stats) const
455  {
456  return generic_add_stat_values_with_converted_timers<true, Duration> (statsetr, output_stats);
457  }
458 
460  // statset
462 
463  template<bool IsAtomic>
465  : m_value_count (value_count)
466  , m_values (new generic_value<IsAtomic>[m_value_count])
467  , m_timept (clock::now ())
468  {
469  //
470  }
471 
472  template<bool IsAtomic>
474  {
475  delete [] m_values;
476  }
477 
479  // generic_stat_counter
481 
482  template<bool IsAtomic>
484  : m_stat_value (0)
485  , m_stat_name (name)
486  {
487  //
488  }
489 
490  template<bool IsAtomic>
491  void
493  {
494  m_stat_value += incr;
495  }
496 
497  template<bool IsAtomic>
498  stat_value
500  {
501  return m_stat_value;
502  }
503 
504  template<bool IsAtomic>
505  const char *
507  {
508  return m_stat_name;
509  }
510 
512  // generic_stat_timer
514 
515  template<bool IsAtomic>
516  generic_stat_timer<IsAtomic>::generic_stat_timer (const char *name /* = NULL */)
517  : m_stat_value (0)
518  , m_stat_name (name)
519  , m_timept (clock::now ())
520  {
521  //
522  }
523 
524  template<bool IsAtomic>
525  void
527  {
528  m_stat_value += d.count ();
529  }
530 
531  template<bool IsAtomic>
532  void
534  {
535  time_point nowpt = clock::now ();
536  time (nowpt - m_timept);
537  m_timept = nowpt;
538  }
539 
540  template<bool IsAtomic>
541  stat_value
543  {
544  return m_stat_value;
545  }
546 
547  template<bool IsAtomic>
548  const char *
550  {
551  return m_stat_name;
552  }
553 
555  // generic_stat_counter_and_timer
557 
558  template<bool IsAtomic>
560  const char *stat_timer_name)
561  : m_stat_counter (stat_counter_name)
562  , m_stat_timer (stat_timer_name)
563  {
564  //
565  }
566 
567  template<bool IsAtomic>
570  {
571  //
572  }
573 
574  template<bool IsAtomic>
575  void
577  {
578  m_stat_counter.increment (incr);
579  m_stat_timer.time (d);
580  }
581 
582  template<bool IsAtomic>
583  void
585  {
586  m_stat_counter.increment (incr);
587  m_stat_timer.time ();
588  }
589 
590  template<bool IsAtomic>
591  stat_value
593  {
594  return m_stat_counter.get_count ();
595  }
596 
597  template<bool IsAtomic>
598  stat_value
600  {
601  return m_stat_timer.get_time ();
602  }
603 
604  template<bool IsAtomic>
605  const char *
607  {
608  return m_stat_counter.get_name ();
609  }
610 
611  template<bool IsAtomic>
612  const char *
614  {
615  return m_stat_timer.get_name ();
616  }
617 
619  // inline functions
621 
622  void
624  {
625  timept = clock::now ();
626  }
627 
628 } // namespace cubperf
629 
630 #endif // _PERF_HPP_
generic_value< IsAtomic > m_stat_value
Definition: perf_def.hpp:89
void increment(statset &statsetr, stat_id id, stat_value incr=1) const
Definition: perf.hpp:261
void generic_time(generic_statset< IsAtomic > &statsetr, stat_id id, duration d) const
Definition: perf.hpp:274
stat_value get_count(void)
Definition: perf.hpp:499
void time_and_increment(statset &statsetr, stat_id id, duration d, stat_value incr=1) const
Definition: perf.hpp:340
generic_value< false > stat_value
Definition: perf_def.hpp:46
typename std::conditional< IsAtomic, std::atomic< std::uint64_t >, std::uint64_t >::type generic_value
Definition: perf_def.hpp:45
stat_definition * m_stat_defs
Definition: perf.hpp:231
std::size_t stat_id
Definition: perf_def.hpp:50
std::size_t m_value_count
Definition: perf.hpp:230
static const std::size_t MAX_VALUE_COUNT
Definition: perf.hpp:131
stat_definition & operator=(const stat_definition &other)
Definition: perf.cpp:61
void get_stat_values_with_converted_timers(const statset &statsetr, stat_value *output_stats) const
Definition: perf.hpp:403
std::string * m_value_names
Definition: perf.hpp:232
void generic_add_stat_values_with_converted_timers(const generic_statset< IsAtomic > &statsetr, stat_value *output_stats) const
Definition: perf.hpp:418
void generic_get_stat_values_with_converted_timers(const generic_statset< IsAtomic > &statsetr, stat_value *output_stats) const
Definition: perf.hpp:375
const char * get_count_name(void)
Definition: perf.hpp:606
void time_and_increment(duration d, stat_value incr=1)
Definition: perf.hpp:576
void generic_time_and_increment(generic_statset< IsAtomic > &statsetr, stat_id id, stat_value incr, duration d) const
Definition: perf.hpp:318
stat_value get_time(void)
Definition: perf.hpp:542
generic_statset(void)=delete
#define assert(x)
std::size_t get_value_count(void) const
Definition: perf.cpp:75
clock::time_point time_point
Definition: perf_def.hpp:40
std::chrono::high_resolution_clock clock
Definition: perf_def.hpp:39
void add_stat_values_with_converted_timers(const statset &statsetr, stat_value *output_stats) const
Definition: perf.hpp:446
Definition: perf.cpp:31
void time(statset &statsetr, stat_id id, duration d) const
Definition: perf.hpp:293
const char * get_name(void)
Definition: perf.hpp:506
generic_stat_counter(const char *name=NULL)
Definition: perf.hpp:483
friend class statset_definition
Definition: perf.hpp:126
#define NULL
Definition: freelistheap.h:34
generic_stat_timer(const char *name=NULL)
Definition: perf.hpp:516
std::size_t m_offset
Definition: perf.hpp:136
generic_value< IsAtomic > * m_values
Definition: perf_def.hpp:58
std::size_t m_stat_count
Definition: perf.hpp:229
generic_stat_timer< IsAtomic > m_stat_timer
Definition: perf_def.hpp:133
void generic_increment(generic_statset< IsAtomic > &statsetr, stat_id id, stat_value incr) const
Definition: perf.hpp:251
const char * get_name(void)
Definition: perf.hpp:549
clock::duration duration
Definition: perf_def.hpp:41
stat_value convert_timeval(stat_value nanosecs) const
Definition: perf.hpp:366
generic_stat_counter< IsAtomic > m_stat_counter
Definition: perf_def.hpp:132
generic_value< IsAtomic > m_stat_value
Definition: perf_def.hpp:107
void increment(stat_value incr=1)
Definition: perf.hpp:492
const char * m_names[MAX_VALUE_COUNT]
Definition: perf.hpp:135
const char * get_time_name(void)
Definition: perf.hpp:613
void reset_timept(time_point &timept)
Definition: perf.hpp:623