timemory  3.2.1
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
components.hpp
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2020, The Regents of the University of California,
4 // through Lawrence Berkeley National Laboratory (subject to receipt of any
5 // required approvals from the U.S. Dept. of Energy). All rights reserved.
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 
25 #pragma once
26 
28 #include "timemory/mpl/types.hpp"
29 #include "timemory/units.hpp"
30 
31 #include "timemory/components/timing/backends.hpp"
34 
35 #include <utility>
36 
37 namespace tim
38 {
39 namespace component
40 {
41 //--------------------------------------------------------------------------------------//
42 /// \struct tim::component::system_clock
43 /// \brief this component extracts only the CPU time spent in kernel-mode.
44 /// Only relevant as a time when a different is computed
45 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
46 struct system_clock : public base<system_clock>
47 {
48  using ratio_t = std::nano;
49  using value_type = int64_t;
51 
52  static std::string label() { return "sys"; }
53  static std::string description() { return "CPU time spent in kernel-mode"; }
54  static value_type record() noexcept
55  {
56  return tim::get_clock_system_now<int64_t, ratio_t>();
57  }
58  TIMEMORY_NODISCARD double get() const noexcept
59  {
60  auto val = load();
61  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
63  }
64  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
65  void start() noexcept { value = record(); }
66  void stop() noexcept
67  {
68  value = (record() - value);
69  accum += value;
70  }
71 };
72 
73 //--------------------------------------------------------------------------------------//
74 /// \struct tim::component::user_clock
75 /// \brief this component extracts only the CPU time spent in user-mode.
76 /// Only relevant as a time when a different is computed
77 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
78 struct user_clock : public base<user_clock>
79 {
80  using ratio_t = std::nano;
81  using value_type = int64_t;
83 
84  static std::string label() { return "user"; }
85  static std::string description() { return "CPU time spent in user-mode"; }
86  static value_type record() noexcept
87  {
88  return tim::get_clock_user_now<int64_t, ratio_t>();
89  }
90  TIMEMORY_NODISCARD double get() const noexcept
91  {
92  auto val = load();
93  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
95  }
96  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
97  void start() noexcept { value = record(); }
98  void stop() noexcept
99  {
100  value = (record() - value);
101  accum += value;
102  }
103 };
104 
105 //--------------------------------------------------------------------------------------//
106 /// \struct tim::component::cpu_clock
107 /// \brief this component extracts only the CPU time spent in both user- and kernel- mode.
108 /// Only relevant as a time when a different is computed
109 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
110 struct cpu_clock : public base<cpu_clock>
111 {
112  using ratio_t = std::nano;
113  using value_type = int64_t;
115 
116  static std::string label() { return "cpu"; }
118  {
119  return "Total CPU time spent in both user- and kernel-mode";
120  }
121  static value_type record() noexcept
122  {
123  return tim::get_clock_cpu_now<int64_t, ratio_t>();
124  }
125  TIMEMORY_NODISCARD double get() const noexcept
126  {
127  auto val = load();
128  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
130  }
131  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
132  void start() noexcept { value = record(); }
133  void stop() noexcept
134  {
135  value = (record() - value);
136  accum += value;
137  }
138 };
139 
140 //--------------------------------------------------------------------------------------//
141 /// \struct tim::component::monotonic_clock
142 /// \brief clock that increments monotonically, tracking the time since an arbitrary
143 /// point, and will continue to increment while the system is asleep.
144 struct monotonic_clock : public base<monotonic_clock>
145 {
146  using ratio_t = std::nano;
147  using value_type = int64_t;
149 
150  static std::string label() { return "monotonic_clock"; }
152  {
153  return "Wall-clock timer which will continue to increment even while the system "
154  "is asleep";
155  }
157  {
158  return tim::get_clock_monotonic_now<int64_t, ratio_t>();
159  }
160  TIMEMORY_NODISCARD double get() const noexcept
161  {
162  auto val = load();
163  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
165  }
166  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
167  void start() noexcept { value = record(); }
168  void stop() noexcept
169  {
170  value = (record() - value);
171  accum += value;
172  }
173 };
174 
175 //--------------------------------------------------------------------------------------//
176 /// \struct tim::component::monotonic_raw_clock
177 /// \brief clock that increments monotonically, tracking the time since an arbitrary point
178 /// like CLOCK_MONOTONIC. However, this clock is unaffected by frequency or time
179 /// adjustments. It should not be compared to other system time sources.
180 struct monotonic_raw_clock : public base<monotonic_raw_clock>
181 {
182  using ratio_t = std::nano;
183  using value_type = int64_t;
185 
186  static std::string label() { return "monotonic_raw_clock"; }
188  {
189  return "Wall-clock timer unaffected by frequency or time adjustments in system "
190  "time-of-day clock";
191  }
193  {
194  return tim::get_clock_monotonic_raw_now<int64_t, ratio_t>();
195  }
196  TIMEMORY_NODISCARD double get() const noexcept
197  {
198  auto val = load();
199  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
201  }
202  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
203  void start() noexcept { value = record(); }
204  void stop() noexcept
205  {
206  value = (record() - value);
207  accum += value;
208  }
209 };
210 
211 //--------------------------------------------------------------------------------------//
212 /// \struct tim::component::thread_cpu_clock
213 /// \brief this clock measures the CPU time within the current thread (excludes
214 /// sibling/child threads).
215 /// Only relevant as a time when a different is computed
216 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
217 struct thread_cpu_clock : public base<thread_cpu_clock>
218 {
219  using ratio_t = std::nano;
220  using value_type = int64_t;
222 
223  static std::string label() { return "thread_cpu"; }
224  static std::string description() { return "CPU-clock timer for the calling thread"; }
225  static value_type record() noexcept
226  {
227  return tim::get_clock_thread_now<int64_t, ratio_t>();
228  }
229  TIMEMORY_NODISCARD double get() const noexcept
230  {
231  auto val = load();
232  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
234  }
235  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
236  void start() noexcept { value = record(); }
237  void stop() noexcept
238  {
239  value = (record() - value);
240  accum += value;
241  }
242 };
243 
244 //--------------------------------------------------------------------------------------//
245 /// \struct tim::component::process_cpu_clock
246 /// \brief this clock measures the CPU time within the current process (excludes child
247 /// processes).
248 /// Only relevant as a time when a different is computed
249 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
250 struct process_cpu_clock : public base<process_cpu_clock>
251 {
252  using ratio_t = std::nano;
253  using value_type = int64_t;
255 
256  static std::string label() { return "process_cpu"; }
258  {
259  return "CPU-clock timer for the calling process (all threads)";
260  }
261  static value_type record() noexcept
262  {
263  return tim::get_clock_process_now<int64_t, ratio_t>();
264  }
265  TIMEMORY_NODISCARD double get() const noexcept
266  {
267  auto val = load();
268  return static_cast<double>(val / static_cast<double>(ratio_t::den) *
270  }
271  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
272  void start() noexcept { value = record(); }
273  void stop() noexcept
274  {
275  value = (record() - value);
276  accum += value;
277  }
278 };
279 
280 //--------------------------------------------------------------------------------------//
281 /// \struct tim::component::cpu_util
282 /// \brief this computes the CPU utilization percentage for the calling process and child
283 /// processes.
284 /// Only relevant as a time when a different is computed
285 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
286 struct cpu_util : public base<cpu_util, std::pair<int64_t, int64_t>>
287 {
288  using ratio_t = std::nano;
289  using value_type = std::pair<int64_t, int64_t>;
292 
293  static std::string label() { return "cpu_util"; }
295  {
296  return "Percentage of CPU-clock time divided by wall-clock time";
297  }
299  {
301  }
302  TIMEMORY_NODISCARD double get() const noexcept
303  {
304  const auto& _data = load();
305  double denom = (_data.second > 0) ? _data.second : 1;
306  double numer = (_data.second > 0) ? _data.first : 0;
307  return 100.0 * static_cast<double>(numer) / static_cast<double>(denom);
308  }
309  double serialization() const noexcept { return get_display(); }
310  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
311 
312  void start() noexcept
313  {
314  if(!m_derive)
315  value = record();
316  }
317 
318  void stop() noexcept
319  {
320  using namespace tim::component::operators;
321  if(!m_derive)
322  {
323  value = (record() - value);
324  accum += value;
325  }
326  }
327 
328  this_type& operator+=(const this_type& rhs) noexcept
329  {
330  accum += rhs.accum;
331  value += rhs.value;
332  return *this;
333  }
334 
335  this_type& operator-=(const this_type& rhs) noexcept
336  {
337  accum -= rhs.accum;
338  value -= rhs.value;
339  return *this;
340  }
341 
342  bool assemble(const wall_clock* wc, const cpu_clock* cc) noexcept
343  {
344  if(wc && cc)
345  m_derive = true;
346  return m_derive;
347  }
348 
349  bool assemble(const wall_clock* wc, const user_clock* uc,
350  const system_clock* sc) noexcept
351  {
352  if(wc && uc && sc)
353  m_derive = true;
354  return m_derive;
355  }
356 
357  bool derive(const wall_clock* wc, const cpu_clock* cc) noexcept
358  {
359  if(m_derive && wc && cc)
360  {
361  value.first = cc->get_value();
362  value.second = wc->get_value();
363  accum += value;
364  return true;
365  }
366  return false;
367  }
368 
369  bool derive(const wall_clock* wc, const user_clock* uc,
370  const system_clock* sc) noexcept
371  {
372  if(m_derive && wc && uc && sc)
373  {
374  value.first = uc->get_value() + sc->get_value();
375  value.second = wc->get_value();
376  accum += value;
377  return true;
378  }
379  return false;
380  }
381 
382  TIMEMORY_NODISCARD bool is_derived() const noexcept { return m_derive; }
383 
384 private:
385  bool m_derive = false;
386 };
387 
388 //--------------------------------------------------------------------------------------//
389 /// \struct tim::component::process_cpu_util
390 /// \brief this computes the CPU utilization percentage for ONLY the calling process
391 /// (excludes child processes).
392 /// Only relevant as a time when a different is computed
393 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
394 struct process_cpu_util : public base<process_cpu_util, std::pair<int64_t, int64_t>>
395 {
396  using ratio_t = std::nano;
397  using value_type = std::pair<int64_t, int64_t>;
400 
401  static std::string label() { return "proc_cpu_util"; }
403  {
404  return "Percentage of CPU-clock time divided by wall-clock time for calling "
405  "process (all threads)";
406  }
408  {
410  }
411  TIMEMORY_NODISCARD double get() const noexcept
412  {
413  const auto& _data = load();
414  double denom = (_data.second > 0) ? _data.second : 1;
415  double numer = (_data.second > 0) ? _data.first : 0;
416  return 100.0 * static_cast<double>(numer) / static_cast<double>(denom);
417  }
418  double serialization() const noexcept { return get_display(); }
419  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
420  void start() noexcept
421  {
422  if(!m_derive)
423  value = record();
424  }
425  void stop() noexcept
426  {
427  using namespace tim::component::operators;
428  if(!m_derive)
429  {
430  value = (record() - value);
431  accum += value;
432  }
433  }
434 
435  this_type& operator+=(const this_type& rhs) noexcept
436  {
437  accum += rhs.accum;
438  value += rhs.value;
439  return *this;
440  }
441 
442  this_type& operator-=(const this_type& rhs) noexcept
443  {
444  accum -= rhs.accum;
445  value -= rhs.value;
446  return *this;
447  }
448 
449  bool assemble(const wall_clock* wc, const process_cpu_clock* cc) noexcept
450  {
451  if(wc && cc)
452  m_derive = true;
453  return m_derive;
454  }
455 
456  bool derive(const wall_clock* wc, const process_cpu_clock* cc) noexcept
457  {
458  if(m_derive && wc && cc)
459  {
460  value.first = cc->get_value();
461  value.second = wc->get_value();
462  accum += value;
463  return true;
464  }
465  return false;
466  }
467 
468  TIMEMORY_NODISCARD bool is_derived() const noexcept { return m_derive; }
469 
470 private:
471  bool m_derive = false;
472 };
473 
474 //--------------------------------------------------------------------------------------//
475 /// \struct tim::component::thread_cpu_util
476 /// \brief this computes the CPU utilization percentage for ONLY the calling thread
477 /// (excludes sibling and child threads).
478 /// Only relevant as a time when a different is computed
479 /// Do not use a single CPU time as an amount of time; it doesn't work that way.
480 struct thread_cpu_util : public base<thread_cpu_util, std::pair<int64_t, int64_t>>
481 {
482  using ratio_t = std::nano;
483  using value_type = std::pair<int64_t, int64_t>;
486 
487  static std::string label() { return "thread_cpu_util"; }
489  {
490  return "Percentage of CPU-clock time divided by wall-clock time for calling "
491  "thread";
492  }
494  {
496  }
497  TIMEMORY_NODISCARD double get() const noexcept
498  {
499  const auto& _data = load();
500  double denom = (_data.second > 0) ? _data.second : 1;
501  double numer = (_data.second > 0) ? _data.first : 0;
502  return 100.0 * static_cast<double>(numer) / static_cast<double>(denom);
503  }
504  double serialization() const noexcept { return get_display(); }
505  TIMEMORY_NODISCARD double get_display() const noexcept { return get(); }
506  void start() noexcept
507  {
508  if(!m_derive)
509  value = record();
510  }
511  void stop() noexcept
512  {
513  using namespace tim::component::operators;
514  if(!m_derive)
515  {
516  value = (record() - value);
517  accum += value;
518  }
519  }
520 
521  this_type& operator+=(const this_type& rhs) noexcept
522  {
523  accum += rhs.accum;
524  value += rhs.value;
525  return *this;
526  }
527 
528  this_type& operator-=(const this_type& rhs) noexcept
529  {
530  accum -= rhs.accum;
531  value -= rhs.value;
532  return *this;
533  }
534 
535  bool assemble(const wall_clock* wc, const thread_cpu_clock* cc) noexcept
536  {
537  if(wc && cc)
538  m_derive = true;
539  return m_derive;
540  }
541 
542  bool derive(const wall_clock* wc, const thread_cpu_clock* cc) noexcept
543  {
544  if(m_derive && wc && cc)
545  {
546  value.first = cc->get_value();
547  value.second = wc->get_value();
548  accum += value;
549  return true;
550  }
551  return false;
552  }
553 
554  TIMEMORY_NODISCARD bool is_derived() const noexcept { return m_derive; }
555 
556 private:
557  bool m_derive = false;
558 };
559 
560 //--------------------------------------------------------------------------------------//
561 } // namespace component
562 } // namespace tim
563 //
564 //--------------------------------------------------------------------------------------//
565 //
Definition: kokkosp.cpp:38
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
static int64_t get_unit()
this component extracts only the CPU time spent in both user- and kernel- mode. Only relevant as a ti...
Definition: components.hpp:111
double get() const noexcept
Definition: components.hpp:125
static std::string description()
Definition: components.hpp:117
static value_type record() noexcept
Definition: components.hpp:121
static std::string label()
Definition: components.hpp:116
double get_display() const noexcept
Definition: components.hpp:131
this computes the CPU utilization percentage for the calling process and child processes....
Definition: components.hpp:287
double get_display() const noexcept
Definition: components.hpp:310
this_type & operator-=(const this_type &rhs) noexcept
Definition: components.hpp:335
this_type & operator+=(const this_type &rhs) noexcept
Definition: components.hpp:328
bool derive(const wall_clock *wc, const user_clock *uc, const system_clock *sc) noexcept
Definition: components.hpp:369
static std::string label()
Definition: components.hpp:293
static std::string description()
Definition: components.hpp:294
static value_type record()
Definition: components.hpp:298
void stop() noexcept
Definition: components.hpp:318
bool is_derived() const noexcept
Definition: components.hpp:382
std::pair< int64_t, int64_t > value_type
Definition: components.hpp:289
bool assemble(const wall_clock *wc, const cpu_clock *cc) noexcept
Definition: components.hpp:342
bool assemble(const wall_clock *wc, const user_clock *uc, const system_clock *sc) noexcept
Definition: components.hpp:349
bool derive(const wall_clock *wc, const cpu_clock *cc) noexcept
Definition: components.hpp:357
double serialization() const noexcept
Definition: components.hpp:309
void start() noexcept
Definition: components.hpp:312
double get() const noexcept
Definition: components.hpp:302
clock that increments monotonically, tracking the time since an arbitrary point, and will continue to...
Definition: components.hpp:145
double get() const noexcept
Definition: components.hpp:160
static value_type record()
Definition: components.hpp:156
double get_display() const noexcept
Definition: components.hpp:166
static std::string label()
Definition: components.hpp:150
static std::string description()
Definition: components.hpp:151
clock that increments monotonically, tracking the time since an arbitrary point like CLOCK_MONOTONIC....
Definition: components.hpp:181
double get() const noexcept
Definition: components.hpp:196
double get_display() const noexcept
Definition: components.hpp:202
static std::string description()
Definition: components.hpp:187
this clock measures the CPU time within the current process (excludes child processes)....
Definition: components.hpp:251
static std::string description()
Definition: components.hpp:257
static value_type record() noexcept
Definition: components.hpp:261
double get() const noexcept
Definition: components.hpp:265
double get_display() const noexcept
Definition: components.hpp:271
this computes the CPU utilization percentage for ONLY the calling process (excludes child processes)....
Definition: components.hpp:395
double get_display() const noexcept
Definition: components.hpp:419
double serialization() const noexcept
Definition: components.hpp:418
bool is_derived() const noexcept
Definition: components.hpp:468
double get() const noexcept
Definition: components.hpp:411
static std::string label()
Definition: components.hpp:401
std::pair< int64_t, int64_t > value_type
Definition: components.hpp:397
bool assemble(const wall_clock *wc, const process_cpu_clock *cc) noexcept
Definition: components.hpp:449
this_type & operator-=(const this_type &rhs) noexcept
Definition: components.hpp:442
bool derive(const wall_clock *wc, const process_cpu_clock *cc) noexcept
Definition: components.hpp:456
this_type & operator+=(const this_type &rhs) noexcept
Definition: components.hpp:435
static std::string description()
Definition: components.hpp:402
this component extracts only the CPU time spent in kernel-mode. Only relevant as a time when a differ...
Definition: components.hpp:47
static value_type record() noexcept
Definition: components.hpp:54
static std::string label()
Definition: components.hpp:52
double get() const noexcept
Definition: components.hpp:58
double get_display() const noexcept
Definition: components.hpp:64
static std::string description()
Definition: components.hpp:53
this clock measures the CPU time within the current thread (excludes sibling/child threads)....
Definition: components.hpp:218
double get() const noexcept
Definition: components.hpp:229
double get_display() const noexcept
Definition: components.hpp:235
static value_type record() noexcept
Definition: components.hpp:225
static std::string label()
Definition: components.hpp:223
static std::string description()
Definition: components.hpp:224
this computes the CPU utilization percentage for ONLY the calling thread (excludes sibling and child ...
Definition: components.hpp:481
double get_display() const noexcept
Definition: components.hpp:505
std::pair< int64_t, int64_t > value_type
Definition: components.hpp:483
bool derive(const wall_clock *wc, const thread_cpu_clock *cc) noexcept
Definition: components.hpp:542
bool is_derived() const noexcept
Definition: components.hpp:554
double get() const noexcept
Definition: components.hpp:497
double serialization() const noexcept
Definition: components.hpp:504
this_type & operator-=(const this_type &rhs) noexcept
Definition: components.hpp:528
static value_type record()
Definition: components.hpp:493
static std::string description()
Definition: components.hpp:488
static std::string label()
Definition: components.hpp:487
this_type & operator+=(const this_type &rhs) noexcept
Definition: components.hpp:521
bool assemble(const wall_clock *wc, const thread_cpu_clock *cc) noexcept
Definition: components.hpp:535
this component extracts only the CPU time spent in user-mode. Only relevant as a time when a differen...
Definition: components.hpp:79
double get_display() const noexcept
Definition: components.hpp:96
static value_type record() noexcept
Definition: components.hpp:86
static std::string description()
Definition: components.hpp:85
double get() const noexcept
Definition: components.hpp:90
static std::string label()
Definition: components.hpp:84
static value_type record() noexcept
Definition: wall_clock.hpp:55