Ocean
Loading...
Searching...
No Matches
HighPerformanceTimer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_HIGH_PERFORMANCE_TIMER_H
9#define META_OCEAN_BASE_HIGH_PERFORMANCE_TIMER_H
10
11#include "ocean/base/Base.h"
14#include "ocean/base/Value.h"
15
16#include <cfloat>
17#include <numeric>
18
19namespace Ocean
20{
21
22/**
23 * This class implements a high performance timer.
24 * Use this timer to measure time durations with high accuracy.<br>
25 * The measurement can be very helpful to detect performance bottlenecks.<br>
26 * Use the HighPerformanceTimer::precision() to retrieve the possible accuracy of this high performance timer.<br>
27 * The implementation is platform dependent.
28 * @ingroup base
29 */
30class OCEAN_BASE_EXPORT HighPerformanceTimer
31{
32 public:
33
34 /**
35 * Definition of CPU ticks.
36 */
37 typedef int64_t Ticks;
38
39 public:
40
41 /**
42 * Creates a new timer and starts the time measurement.
43 */
45
46 /**
47 * (Re-)starts the time measurement.
48 */
49 inline void start();
50
51 /**
52 * Returns the measured time since the timer has been started in seconds.
53 * @return Measured seconds
54 */
55 double seconds() const;
56
57 /**
58 * Returns the measured time since the timer has been started in milliseconds.
59 * @return Measured milliseconds
60 */
61 double mseconds() const;
62
63 /**
64 * Returns the measured time since the timer has been started in microseconds.
65 * @return Measured microseconds
66 */
67 double yseconds() const;
68
69 /**
70 * Returns the measured time since the timer has been started in nanoseconds.
71 * @return Measured nanoseconds
72 */
73 double nseconds() const;
74
75 /**
76 * Returns the precision of the timer.
77 * @return Countable ticks per seconds
78 */
79 static Ticks precision();
80
81 /**
82 * Returns the recent CPU ticks.
83 * @return Recent CPU ticks
84 */
85 static Ticks ticks();
86
87 /**
88 * Converts a given CPU tick into seconds regarding the resolution of the timer.
89 * @param ticks The ticks to convert
90 * @return The Number of seconds matching with the given CPU ticks
91 */
92 static inline double ticks2seconds(const Ticks ticks);
93
94 protected:
95
96 /**
97 * Returns the resolution of the timer in ticks per second
98 * @return Ticks per second
99 */
101
102 protected:
103
104 /// The number of CPU ticks when starting the timer.
105 Ticks ticksStart_ = Ticks(0);
106};
107
108#ifdef OCEAN_USE_EXTERNAL_PRIVACY_CONFIRM_TICKS
109
110/**
111 * Returns the recent CPU ticks which will contain a random offset which is constant through the execution of the process.
112 * @return Recent CPU ticks with random offset
113 */
115
116#endif // OCEAN_USE_EXTERNAL_PRIVACY_CONFIRM_TICKS
117
118/**
119 * This class implements a simple module gathering high performance timer statistics.
120 * The class is not thread-safe.
121 * @ingroup base
122 */
123class OCEAN_BASE_EXPORT HighPerformanceStatistic
124{
125 public:
126
127 /**
128 * Definition of a vector storing performance measurements.
129 */
130 typedef std::vector<double> Measurements;
131
132 /**
133 * This class defines a scoped high performance statistic module.
134 * Use this scoped module in combination with a high performance statistic object to add a new performance measurement during the existence of this module.
135 * @ingroup base
136 */
137 class OCEAN_BASE_EXPORT ScopedStatistic
138 {
139 public:
140
141 /**
142 * Creates a new scoped statistic object and starts a new measurement.
143 * @param performance High performance statistic object receiving the scoped measurement.
144 */
145 inline explicit ScopedStatistic(HighPerformanceStatistic& performance);
146
147 /**
148 * Destructs a scoped statistic object and stops the measurement.
149 */
150 inline ~ScopedStatistic();
151
152 /**
153 * Explicitly releases the object and does not wait until the scope ends.
154 */
155 inline void release();
156
157 private:
158
159 /**
160 * Deleted copy constructor.
161 */
163
164 /**
165 * Deleted copy operator.
166 * @return Reference to this object
167 */
169
170 private:
171
172 /// High performance statistic object receiving the measurement value.
173 HighPerformanceStatistic* statisticPerformance;
174 };
175
176 public:
177
178 /**
179 * Creates a new statistic module.
180 */
182
183 /**
184 * Returns the first measurement time in seconds.
185 * @return First measurement time, in [sec]
186 */
187 inline double first() const;
188
189 /**
190 * Returns the first measurement time in milliseconds.
191 * @return First measurement time, in [ms]
192 */
193 inline double firstMseconds() const;
194
195 /**
196 * Returns the second measurement time in seconds.
197 * @return Second measurement time, in [sec]
198 */
199 inline double second() const;
200
201 /**
202 * Returns the second measurement time in milliseconds.
203 * @return Second measurement time, in [ms]
204 */
205 inline double secondMseconds() const;
206
207 /**
208 * Returns the best measurement time in seconds.
209 * @return Best measurement time, in [sec]
210 */
211 inline double best() const;
212
213 /**
214 * Returns the best measurement time in milliseconds.
215 * @return Best measurement time, in [ms]
216 */
217 inline double bestMseconds() const;
218
219 /**
220 * Returns the worst measurement time in seconds.
221 * @return Worst measurement time, in [sec]
222 */
223 inline double worst() const;
224
225 /**
226 * Returns the worst measurement time in milliseconds.
227 * @return Worst measurement time, in [ms]
228 */
229 inline double worstMseconds() const;
230
231 /**
232 * Returns the last measurement time in seconds.
233 * @return Last measurement time, in [sec]
234 */
235 inline double last() const;
236
237 /**
238 * Returns the last (most recent measurement time in milliseconds.
239 * @return Last measurement time, in [ms]
240 */
241 inline double lastMseconds() const;
242
243 /**
244 * Returns the average measurement time in seconds.
245 * @return Average measurement time, in [sec]
246 */
247 double average() const;
248
249 /**
250 * Returns the average measurement time in milliseconds.
251 * @return Average measurement time, in [ms]
252 */
253 inline double averageMseconds() const;
254
255 /**
256 * Returns the average number of CPU cycles needed for one operation.
257 * @param operations The number of operation that has been invoked during each measurement, with range [1, infinity)
258 * @param clockRate The number of clock cycles per second of the CPU, e.g., 3.8GHz, with range [1, infinity)
259 * @return The average number of CPU cycles needed, with range (0, infinity), -1 if no valid measurement exists
260 */
261 inline double averageCyclesPerOperation(const double operations, const double clockRate = 3800000000.0) const;
262
263 /**
264 * Returns the median measurement time in seconds.
265 * @return Median measurement time, in [sec]
266 */
267 double median() const;
268
269 /**
270 * Returns the median measurement time in milliseconds.
271 * @return Median measurement time, in [ms]
272 */
273 double medianMseconds() const;
274
275 /**
276 * Returns a specific percentile (e.g., P50 = median, P90, P95, etc.) measurement time in seconds.
277 * @param value The percentile to be returned, with range [0, 1]
278 * @return The measurement for the specified percentile, in seconds
279 */
280 double percentile(double value) const;
281
282 /**
283 * Returns a specific percentile (e.g., P50 = median, P90, P95, etc.) measurement time in milliseconds.
284 * @param value The percentile to be returned, with range [0, 1]
285 * @return The measurement for the specified percentile, in milliseconds
286 */
287 double percentileMseconds(double value) const;
288
289 /**
290 * Returns the total measurement time in seconds.
291 * @return Total measurement time, in [sec]
292 */
293 inline double total() const;
294
295 /**
296 * Returns the total measurement time in milliseconds.
297 * @return Total measurement time, in [ms]
298 */
299 inline double totalMseconds() const;
300
301 /**
302 * Returns the current (still) running measurement time in seconds.
303 * @return Current still running measurement time, in [sec]
304 */
305 inline double running() const;
306
307 /**
308 * Returns the current (still) running measurement time in milliseconds.
309 * @return Current still running measurement time, in [ms]
310 */
311 inline double runningMseconds() const;
312
313 /**
314 * Returns the number of measurements.
315 * @return Measurement numbers
316 */
317 inline size_t measurements() const;
318
319 /**
320 * Returns whether currently a measurement is running.
321 * @return True, if so
322 */
323 inline bool isRunning() const;
324
325 /**
326 * Starts a new measurement.
327 */
328 void start();
329
330 /**
331 * Starts a new measurement if the given value is True, otherwise nothing happens.
332 * @param value True; to start a new measurement; False, to ignore this call
333 */
334 void startIf(const bool value);
335
336 /**
337 * Stops a measurement.
338 */
339 void stop();
340
341 /**
342 * Stops a measurement.
343 * @param value True; to stop the measurement; False, to ignore this call
344 */
345 void stopIf(const bool value);
346
347 /**
348 * Skips a started measurement.
349 * The measurement will not be voted.
350 */
351 void skip();
352
353 /**
354 * Skips a started measurement.
355 * The measurement will not be voted.
356 * @param value True; to skip the measurement; False, to ignore this call
357 */
358 void skipIf(const bool value);
359
360 /**
361 * Resets all gathered statistics.
362 */
363 void reset();
364
365 /**
366 * Returns a string with the relevant performance information of this statistic object.
367 * @param precision The number of decimal places displayed, with range [1, infinity)
368 * @return The resulting string
369 */
370 std::string toString(const unsigned int precision = 2u) const;
371
372 /**
373 * Returns whether at least one measurement has been done.
374 * @return True, if so
375 */
376 explicit inline operator bool() const;
377
378 /**
379 * Adds measurements from another object to this statistic object.
380 * @param right The statistic object of which the measurements will be added to this object
381 * @return Reference to this object
382 */
384
385 private:
386
387 /// High performance timer.
389
390 /// The individual measurements in order as measured.
392
393 /// Best measurement time in seconds.
394 double best_ = DBL_MAX;
395
396 /// Worst measurement time in seconds.
397 double worst_ = -DBL_MAX;
398
399 /// Entire measurement time in seconds.
400 double total_ = 0.0;
401
402 /// State determining whether one measurement is active currently.
403 bool started_ = false;
404};
405
406/**
407 * The HighPerformanceBenchmark object allows to benchmark algorithms with individual categories.
408 * Benchmarking needs to be started before it can be used.<br>
409 * The class is thread-safe.
410 * This class creates flat and/or hierarchical reports. In the case of the former, the categories are sorted by their CPU time. For hierarchical
411 * reports, the category names can be expanded using a delimiter, for example `Foo::Bar` where `Bar` is a sub-category of `Foo`. In this report the
412 * top-level categories (like `Foo`) will be sorted by their total CPU time which is accumulated over all of their sub-categories (like `Foo::Bar`).
413 *
414 * Usage Example:
415 * <pre>
416 * void SomeClass::computeSomething(...)
417 * {
418 * HighPerformanceBenchmark::ScopedCategory scopedBenchmark("AlgorithmName");
419 * function0();
420 * function1();
421 * ...
422 * }
423 *
424 * void SomeClass::function0(...)
425 * {
426 * HighPerformanceBenchmark::ScopedCategory scopedBenchmark("AlgorithmName::Function0");
427 * ...
428 * }
429 *
430 * void SomeClass::function1(...)
431 * {
432 * HighPerformanceBenchmark::ScopedCategory scopedBenchmark("AlgorithmName::Function1");
433 * utilityFunction0();
434 * ...
435 * }
436 *
437 * void Utility::utilityFunction0(...)
438 * {
439 * HighPerformanceBenchmark::ScopedCategory scopedBenchmark("UtilityFunction0");
440 * ...
441 * }
442 *
443 * int main()
444 * {
445 * HighPerformanceBenchmark::get().start();
446 *
447 * while (keepLooping)
448 * {
449 * SomeClass::computeSomething();
450 * }
451 *
452 * HighPerformanceBenchmark::get().stop();
453 *
454 * // Get the normal or hierarchical performance report
455 * const std::vector<std::string> report = HighPerformanceBenchmark::get().report();
456 * const std::vector<std::string> reportWithHierarchies = HighPerformanceBenchmark::get().reportWithHierarchies();
457 * }
458 * </pre>
459 *
460 * which will result in something similar to the following for the normal report:
461 * <pre>
462 * Name | ...
463 * AlgorithmName | ...
464 * UtilityFunction0 | ...
465 * AlgorithmName::Function0 | ...
466 * AlgorithmName::Function1 | ...
467 * </pre>
468 * and for the hierarchical report the output will be similar to this (sub-categories will be appear indented):
469 * <pre>
470 * Name | ...
471 * AlgorithmName | ...
472 * Function0 | ...
473 * Function1 | ...
474 * UtilityFunction0 | ...
475 * </pre>
476 * Of course, the actual order of the categories depends on their proportional contribution to the overall measured CPU time
477 * @ingroup base
478 */
479class OCEAN_BASE_EXPORT HighPerformanceBenchmark : public Singleton<HighPerformanceBenchmark>
480{
482
483 public:
484
485 /**
486 * Definition of a vector holding measurements in seconds.
487 */
488 typedef std::vector<double> MeasurementsSeconds;
489
490 /**
491 * Definition of a map mapping category names to measurements.
492 */
493 typedef std::unordered_map<std::string, MeasurementsSeconds> MeasurementMap;
494
495 /// Forward declaration
496 class Category;
497
498 /// Typedef for a vector of categories
499 typedef std::vector<Category> Categories;
500
501 /**
502 * This class defines a hierarchical category
503 * This class is used to group categories based on their names into a hierarchy. A hierarchy of categories is created by appending the name of a
504 * sub-category to the name of category, using a delimiter between both names, for example "Foo::Bar" is a sub-category of "Foo". This process can
505 * be repeated recursively ("Foo::Bar::Baz"). Categories without a delimiter in their name - or which cannot be matched otherwise - will be
506 * considered top-level categories ("Foo").
507 * @ingroup base
508 */
510 {
511 public:
512
513 /**
514 * Deleted default constructor.
515 */
516 Category() = delete;
517
518 /**
519 * Constructor
520 * @param categoryName The name of the category, must be valid
521 * @param measurementsSeconds The measurements in seconds that have been made by `HighPerformanceBenchmark` for this category, must be valid and non-empty
522 * @param categoryNameDelimiter The delimiter that separate the levels of hierarchy in the category names.
523 */
524 Category(const std::string& categoryName, const MeasurementsSeconds& measurementsSeconds, const std::string& categoryNameDelimiter);
525
526 /**
527 * Adds a sub-category to this category
528 * @param subCategoryName The name of the category that will be added as a sub-category to this category, must be valid
529 * @param measurementsSeconds The measurements in seconds that have been made by `HighPerformanceBenchmark` for the new sub-category, must be valid and non-empty
530 */
531 bool addSubCategory(const std::string& subCategoryName, const MeasurementsSeconds& measurementsSeconds);
532
533 /**
534 * Returns the sub-categories of this category
535 * @return The sub-categories
536 */
537 const Categories& subCategories() const;
538
539 /**
540 * Returns the name of this category
541 * @return The name
542 */
543 const std::string& categoryName() const;
544
545 /**
546 * Computes the sum of all measurements in this category and all of its sub-categories
547 * @return The sum
548 */
550
551 /**
552 * Creates a performance report as a matrix of string tokens
553 * The token matrix is a means to determine the max. column widths in the final report. This alignment step does not happen here, cf. `HighPerformanceBenchmark::reportWithHierarchies()`
554 * @param tokenMatrix The resulting matrix of tokens.
555 * @param referenceSeconds The optional number of seconds that should be used to compute the percentage of CPU runtime of this categories (and it's sub-categories); for values <= 0.0 the percentage will be computed internally for this category only, range: (-infinity, infinity)
556 * @param numberIndentationSpace The optional number of spaces that should be prepended to the names of the categories in the final report (to visualize the hierarchy)
557 * @param categoryNameDelimiter The delimiter that separate the levels of hierarchy in the category names.
558 * @param addColumnDescriptions True, adds a row to the resulting token matrix that contains human-readable descriptions of the columns of the matrix, otherwise no descriptions will be added
559 * @param valuesAsStrings True, all cells will be of type string; False, column descriptions and category names will be reported as string and all other values as double or integer.
560 * @param includeSubCategories True, all sub-categories of the this category will be added to the token matrix as well; False, they will be ignored
561 * @return True, if the generation of the token matrix was successful, otherwise false
562 * @sa HighPerformanceBenchmark::reportWithHierarchies()
563 */
564 bool reportAsTokenMatrix(std::vector<std::vector<Value>>& tokenMatrix, const double referenceSeconds = 0.0, const unsigned numberIndentationSpace = 0u, const std::string& categoryNameDelimiter = "::", const bool addColumnDescriptions = false, const bool valuesAsStrings = true, const bool includeSubCategories = true) const;
565
566 /**
567 * Recursively sorts a list of categories by their total CPU times in descending order
568 * @param categories The categories that will be sorted
569 */
570 static void sort(Categories& categories);
571
572 /**
573 * Compares the recursive CPU times of two categories
574 * @param category0 The first category that will be used in this comparison, must be valid
575 * @param category1 The second category that will be used in this comparison, must be valid
576 * @return True if the CPU time of the first category is equal or larger than the second, otherwise false
577 */
578 static bool greaterCpuTime(const Category& category0, const Category& category1);
579
580 protected:
581
582 /// The human-readable name of this category, e.g., "Foo"
583 std::string categoryName_;
584
585 /// The sorted measurements for this category
587
588 /// The delimiter that is used to separate different levels of the hierarchy in the human-readable category name, e.g. "::"
590
591 /// The list of sub-categories, e.g. "Foo::Bar", "Foo::Bar::Test", "Foo::Baz", etc.
592 std::vector<Category> subCategories_;
593 };
594
595 public:
596
597 /**
598 * This class implements a scoped benchmark category.
599 * There must not exist more than one object for each category at the same time.
600 */
601 class OCEAN_BASE_EXPORT ScopedCategory
602 {
603 public:
604
605 /**
606 * Creates a new scoped category with specific name.
607 * Benchmarking will be active as long as the object exists (the execution time of the category will be increased as long as the object exists).
608 * @param name The name of the category, must be valid
609 */
610 explicit inline ScopedCategory(std::string name);
611
612 /**
613 * Destructs the scoped category.
614 * Benchmarking for this category will end.
615 */
616 inline ~ScopedCategory();
617
618 /**
619 * Explicitly skips benchmarking for this category before the actual scope ends, e.g., if a function did not finish due to an error.
620 */
621 inline void skip();
622
623 /**
624 * Explicitly ends benchmarking for this category before the actual scope ends.
625 */
626 inline void release();
627
628 /**
629 * Changes the benchmarking category, releases the current category and creates a new one.
630 * @param name The new name of the category, empty to release the current category without creating a new one
631 */
632 inline void change(std::string name);
633
634 protected:
635
636 /**
637 * Not existing copy constructor.
638 * @param scopedCategory The object that would be copied
639 */
640 ScopedCategory(const ScopedCategory& scopedCategory) = delete;
641
642 /**
643 * Not existing copy constructor.
644 * @param scopedCategory The object that would be copied
645 */
646 ScopedCategory& operator=(const ScopedCategory& scopedCategory) = delete;
647
648 protected:
649
650 /// The name of the benchmark category.
651 std::string name_;
652
653 /// The CPU ticks when the benchmark of this category started.
655 };
656
657 public:
658
659 /**
660 * Starts benchmarking.
661 * @return True, if succeeded
662 * @see stop(), isRunning().
663 */
664 bool start();
665
666 /**
667 * Stops benchmarking.
668 * @return True, if succeeded
669 * @see start(), isRunning().
670 */
671 bool stop();
672
673 /**
674 * Rests all benchmark categories and measurements.
675 */
676 void reset();
677
678 /**
679 * Returns whether benchmarking is currently active; False by default.
680 * @return True, if so
681 */
682 bool isRunning() const;
683
684 /**
685 * Returns the map with category names and measurement objects.
686 * @return The measurement map
687 */
689
690 /**
691 * Creates a performance report as a readable string.
692 * @param referenceCategory Optional reference category for to add relative performance values to the report
693 * @return The report as readable string, one string for each line in the report
694 */
695 std::vector<std::string> report(const std::string& referenceCategory = std::string()) const;
696
697 /**
698 * Creates a performance report for a hierarchy of categories as a human-readable string.
699 *
700 * A hierarchy of categories is created by appending the name of a sub-category to the name of category, using a delimiter between both names,
701 * for example "Foo::Bar" is a sub-category of "Foo". This process can be repeated recursively ("Foo::Bar::Baz"). Categories without a delimiter
702 * in their name - or which cannot be matched otherwise - will be considered top-level categories ("Foo").
703 *
704 * The final report will list either 1) all top-level categories with their subsumed sub-categories (which will be indented) or 2) a specific
705 * top-level category. All categories and sub-categories will be sorted by their total CPU-time in descending order.
706 * @param report The resulting report as a readable string, one string for each line in the report
707 * @param referenceCategory The optional reference category for to add relative performance values to the report
708 * @param categoryNameDelimiter The optional delimiter that is used to separate levels of categories in a hierarchy
709 * @return True, if the generation of the report was successful, otherwise false
710 */
711 bool reportWithHierarchies(std::vector<std::string>& report, const std::string& referenceCategory = std::string(), const std::string& categoryNameDelimiter = "::") const;
712
713 /**
714 * Returns the number of measurements of a specific category.
715 * @param category The category for which the number of measurements will be returned
716 * @return The number of measurements, with range [0, infinity)
717 */
718 size_t measurements(const std::string& category);
719
720 /**
721 * Creates a hierarchy of categories based on their names from a map of measurements
722 * @param measurementMap The map of measurements (category -> measurements) for which a hierarchy of categories will be created
723 * @param categoryNameDelimiter The delimiter that is used to separate levels of categories in a hierarchy
724 * @return The hierarchy
725 */
726 static Categories createCategoryHierarchy(const MeasurementMap& measurementMap, const std::string& categoryNameDelimiter);
727
728 /**
729 * Given a hierarchy of categories with measurements, create a matrix with the performance information
730 * The output of this function is a matrix where each cell contains the information that the final report will contain. This intermediate container makes it easy to print the report with aligned columns.
731 * @param categories The hierarchy of categories for which a token matrix will created, must be valid and not empty.
732 * @param referenceCategory The optional reference category for to add relative performance values to the report
733 * @param categoryNameDelimiter The optional delimiter that is used to separate levels of categories in a hierarchy
734 * @param valuesAsStrings True, all cells will be of type string; False, column descriptions and category names will be reported as string and all other values as double or integer.
735 * @param tokenMatrix The resulting token matrix for all categories.
736 * @return True, if the generation of the token matrix was successful, otherwise false.
737 */
738 static bool createTokenMatrixFromCategoryHierarchy(const Categories& categories, const std::string referenceCategory, const std::string& categoryNameDelimiter, const bool valuesAsStrings, std::vector<std::vector<Value>>& tokenMatrix);
739
740 protected:
741
742 /**
743 * Adds a benchmark measurement for a specified category.
744 * @param name The name of the category
745 * @param measurement The benchmark measurement in seconds, with range [0, infinity)
746 */
747 void addMeasurement(const std::string& name, const double measurement);
748
749 protected:
750
751 /**
752 * Default constructor.
753 */
755
756 /**
757 * Destructs an object.
758 */
760
761 protected:
762
763 /// The map mapping category names to their measurement objects.
765
766 /// True, if benchmarking is running, false by default.
768
769 /// The lock object.
770 mutable Lock lock_;
771};
772
774 statisticPerformance(&performance)
775{
777}
778
783
785{
786 if (statisticPerformance)
787 {
788 statisticPerformance->stop();
789 statisticPerformance = nullptr;
790 }
791}
792
794{
795 ticksStart_ = ticks();
796}
797
799{
800 ocean_assert(precision() != Ticks(0));
801 return double(ticks) / double(precision());
802}
803
805{
806 if (measurements_.empty())
807 {
808 return -1.0;
809 }
810
811 return measurements_.front();
812}
813
815{
816 if (measurements_.empty())
817 {
818 return -1.0;
819 }
820
821 return measurements_.front() * 1000.0;
822}
823
825{
826 if (measurements_.size() < 2)
827 {
828 return -1.0;
829 }
830
831 return measurements_[1];
832}
833
835{
836 if (measurements_.size() < 2)
837 {
838 return -1.0;
839 }
840
841 return measurements_[1] * 1000.0;
842}
843
845{
846 if (measurements_.empty())
847 {
848 return -1.0;
849 }
850
851 return best_;
852}
853
855{
856 if (measurements_.empty())
857 {
858 return -1.0;
859 }
860
861 return best_ * 1000.0;
862}
863
865{
866 if (measurements_.empty())
867 {
868 return -1.0;
869 }
870
871 return worst_;
872}
873
875{
876 if (measurements_.empty())
877 {
878 return -1.0;
879 }
880
881 return worst_ * 1000.0;
882}
883
885{
886 if (measurements_.empty())
887 {
888 return -1.0;
889 }
890
891 return measurements_.back();
892}
893
895{
896 if (measurements_.empty())
897 {
898 return -1.0;
899 }
900
901 return measurements_.back() * 1000.0;
902}
903
905{
906 return average() * 1000.0;
907}
908
909inline double HighPerformanceStatistic::averageCyclesPerOperation(const double operations, const double clockRate) const
910{
911 ocean_assert(operations > 0.0 && clockRate > 0.0);
912
913 const double seconds = average();
914 if (seconds <= 0)
915 {
916 return -1;
917 }
918
919 const double operationsPerSecond = operations / seconds;
920 ocean_assert(operationsPerSecond > 0.0);
921
922 const double cyclesPerOperation = clockRate / operationsPerSecond;
923
924 return cyclesPerOperation;
925}
926
928{
929 return total_;
930}
931
933{
934 return total() * 1000.0;
935}
936
938{
939 return measurements_.size();
940}
941
943{
944 return timer_.seconds();
945}
946
948{
949 return running() * 1000.0;
950}
951
953{
954 return started_;
955}
956
957inline HighPerformanceStatistic::operator bool() const
958{
959 return !measurements_.empty();
960}
961
962
963inline std::ostream& operator<<(std::ostream& stream, const HighPerformanceStatistic& highPerformanceStatistic)
964{
965 stream << highPerformanceStatistic.toString();
966
967 return stream;
968}
969
970template <bool tActive>
971MessageObject<tActive>& operator<<(MessageObject<tActive>& messageObject, const HighPerformanceStatistic& highPerformanceStatistic)
972{
973 messageObject << highPerformanceStatistic.toString();
974
975 return messageObject;
976}
977
978template <bool tActive>
979MessageObject<tActive>& operator<<(MessageObject<tActive>&& messageObject, const HighPerformanceStatistic& highPerformanceStatistic)
980{
981 messageObject << highPerformanceStatistic.toString();
982
983 return messageObject;
984}
985
987 name_(std::move(name)),
988 startTicks_(HighPerformanceTimer::ticks())
989{
990 // nothing to do here
991}
992
997
999{
1000 name_.clear();
1001}
1002
1004{
1005 if (!name_.empty())
1006 {
1008 ocean_assert(startTicks_ <= stopTicks);
1009
1010 const HighPerformanceTimer::Ticks ticks = stopTicks - startTicks_;
1011
1012 const double measurement = HighPerformanceTimer::ticks2seconds(ticks);
1013 HighPerformanceBenchmark::get().addMeasurement(name_, measurement);
1014
1015 name_.clear();
1016 }
1017}
1018
1020{
1021 if (name_ == name)
1022 {
1023 return;
1024 }
1025
1026 release();
1027
1028 if (!name.empty())
1029 {
1030 name_ = std::move(name);
1031 startTicks_ = HighPerformanceTimer::ticks();
1032 }
1033}
1034
1036 isRunning_(false)
1037{
1038 // nothing to do here
1039}
1040
1042{
1043 // nothing to do here
1044}
1045
1046}
1047
1048#endif // META_OCEAN_BASE_HIGH_PERFORMANCE_TIMER_H
This class defines a hierarchical category This class is used to group categories based on their name...
Definition HighPerformanceTimer.h:510
const std::string & categoryName() const
Returns the name of this category.
double computeRecursiveSumSeconds() const
Computes the sum of all measurements in this category and all of its sub-categories.
const Categories & subCategories() const
Returns the sub-categories of this category.
Category(const std::string &categoryName, const MeasurementsSeconds &measurementsSeconds, const std::string &categoryNameDelimiter)
Constructor.
static void sort(Categories &categories)
Recursively sorts a list of categories by their total CPU times in descending order.
std::string categoryNameDelimiter_
The delimiter that is used to separate different levels of the hierarchy in the human-readable catego...
Definition HighPerformanceTimer.h:589
bool addSubCategory(const std::string &subCategoryName, const MeasurementsSeconds &measurementsSeconds)
Adds a sub-category to this category.
MeasurementsSeconds sortedMeasurementsSeconds_
The sorted measurements for this category.
Definition HighPerformanceTimer.h:586
std::vector< Category > subCategories_
The list of sub-categories, e.g. "Foo::Bar", "Foo::Bar::Test", "Foo::Baz", etc.
Definition HighPerformanceTimer.h:592
static bool greaterCpuTime(const Category &category0, const Category &category1)
Compares the recursive CPU times of two categories.
Category()=delete
Deleted default constructor.
std::string categoryName_
The human-readable name of this category, e.g., "Foo".
Definition HighPerformanceTimer.h:583
bool reportAsTokenMatrix(std::vector< std::vector< Value > > &tokenMatrix, const double referenceSeconds=0.0, const unsigned numberIndentationSpace=0u, const std::string &categoryNameDelimiter="::", const bool addColumnDescriptions=false, const bool valuesAsStrings=true, const bool includeSubCategories=true) const
Creates a performance report as a matrix of string tokens The token matrix is a means to determine th...
This class implements a scoped benchmark category.
Definition HighPerformanceTimer.h:602
std::string name_
The name of the benchmark category.
Definition HighPerformanceTimer.h:651
ScopedCategory & operator=(const ScopedCategory &scopedCategory)=delete
Not existing copy constructor.
void change(std::string name)
Changes the benchmarking category, releases the current category and creates a new one.
Definition HighPerformanceTimer.h:1019
HighPerformanceTimer::Ticks startTicks_
The CPU ticks when the benchmark of this category started.
Definition HighPerformanceTimer.h:654
ScopedCategory(std::string name)
Creates a new scoped category with specific name.
Definition HighPerformanceTimer.h:986
void skip()
Explicitly skips benchmarking for this category before the actual scope ends, e.g....
Definition HighPerformanceTimer.h:998
void release()
Explicitly ends benchmarking for this category before the actual scope ends.
Definition HighPerformanceTimer.h:1003
ScopedCategory(const ScopedCategory &scopedCategory)=delete
Not existing copy constructor.
~ScopedCategory()
Destructs the scoped category.
Definition HighPerformanceTimer.h:993
The HighPerformanceBenchmark object allows to benchmark algorithms with individual categories.
Definition HighPerformanceTimer.h:480
size_t measurements(const std::string &category)
Returns the number of measurements of a specific category.
std::vector< std::string > report(const std::string &referenceCategory=std::string()) const
Creates a performance report as a readable string.
std::unordered_map< std::string, MeasurementsSeconds > MeasurementMap
Definition of a map mapping category names to measurements.
Definition HighPerformanceTimer.h:493
bool isRunning() const
Returns whether benchmarking is currently active; False by default.
bool isRunning_
True, if benchmarking is running, false by default.
Definition HighPerformanceTimer.h:767
bool reportWithHierarchies(std::vector< std::string > &report, const std::string &referenceCategory=std::string(), const std::string &categoryNameDelimiter="::") const
Creates a performance report for a hierarchy of categories as a human-readable string.
MeasurementMap measurementMap_
The map mapping category names to their measurement objects.
Definition HighPerformanceTimer.h:764
static bool createTokenMatrixFromCategoryHierarchy(const Categories &categories, const std::string referenceCategory, const std::string &categoryNameDelimiter, const bool valuesAsStrings, std::vector< std::vector< Value > > &tokenMatrix)
Given a hierarchy of categories with measurements, create a matrix with the performance information T...
~HighPerformanceBenchmark()
Destructs an object.
Definition HighPerformanceTimer.h:1041
void reset()
Rests all benchmark categories and measurements.
Lock lock_
The lock object.
Definition HighPerformanceTimer.h:770
HighPerformanceBenchmark()
Default constructor.
Definition HighPerformanceTimer.h:1035
void addMeasurement(const std::string &name, const double measurement)
Adds a benchmark measurement for a specified category.
std::vector< Category > Categories
Typedef for a vector of categories.
Definition HighPerformanceTimer.h:499
static Categories createCategoryHierarchy(const MeasurementMap &measurementMap, const std::string &categoryNameDelimiter)
Creates a hierarchy of categories based on their names from a map of measurements.
std::vector< double > MeasurementsSeconds
Definition of a vector holding measurements in seconds.
Definition HighPerformanceTimer.h:488
bool start()
Starts benchmarking.
MeasurementMap measurementMap() const
Returns the map with category names and measurement objects.
bool stop()
Stops benchmarking.
This class defines a scoped high performance statistic module.
Definition HighPerformanceTimer.h:138
ScopedStatistic(HighPerformanceStatistic &performance)
Creates a new scoped statistic object and starts a new measurement.
Definition HighPerformanceTimer.h:773
HighPerformanceStatistic * statisticPerformance
High performance statistic object receiving the measurement value.
Definition HighPerformanceTimer.h:173
ScopedStatistic & operator=(const ScopedStatistic &)=delete
Deleted copy operator.
void release()
Explicitly releases the object and does not wait until the scope ends.
Definition HighPerformanceTimer.h:784
~ScopedStatistic()
Destructs a scoped statistic object and stops the measurement.
Definition HighPerformanceTimer.h:779
ScopedStatistic(const ScopedStatistic &)=delete
Deleted copy constructor.
This class implements a simple module gathering high performance timer statistics.
Definition HighPerformanceTimer.h:124
double running() const
Returns the current (still) running measurement time in seconds.
Definition HighPerformanceTimer.h:942
std::vector< double > Measurements
Definition of a vector storing performance measurements.
Definition HighPerformanceTimer.h:130
HighPerformanceTimer timer_
High performance timer.
Definition HighPerformanceTimer.h:388
std::string toString(const unsigned int precision=2u) const
Returns a string with the relevant performance information of this statistic object.
double percentileMseconds(double value) const
Returns a specific percentile (e.g., P50 = median, P90, P95, etc.) measurement time in milliseconds.
double totalMseconds() const
Returns the total measurement time in milliseconds.
Definition HighPerformanceTimer.h:932
HighPerformanceStatistic & operator+=(const HighPerformanceStatistic &right)
Adds measurements from another object to this statistic object.
double medianMseconds() const
Returns the median measurement time in milliseconds.
bool isRunning() const
Returns whether currently a measurement is running.
Definition HighPerformanceTimer.h:952
double worstMseconds() const
Returns the worst measurement time in milliseconds.
Definition HighPerformanceTimer.h:874
Measurements measurements_
The individual measurements in order as measured.
Definition HighPerformanceTimer.h:391
double worst() const
Returns the worst measurement time in seconds.
Definition HighPerformanceTimer.h:864
double worst_
Worst measurement time in seconds.
Definition HighPerformanceTimer.h:397
void startIf(const bool value)
Starts a new measurement if the given value is True, otherwise nothing happens.
double first() const
Returns the first measurement time in seconds.
Definition HighPerformanceTimer.h:804
void stop()
Stops a measurement.
double best_
Best measurement time in seconds.
Definition HighPerformanceTimer.h:394
void reset()
Resets all gathered statistics.
double best() const
Returns the best measurement time in seconds.
Definition HighPerformanceTimer.h:844
HighPerformanceStatistic()
Creates a new statistic module.
double average() const
Returns the average measurement time in seconds.
double second() const
Returns the second measurement time in seconds.
Definition HighPerformanceTimer.h:824
double total_
Entire measurement time in seconds.
Definition HighPerformanceTimer.h:400
double secondMseconds() const
Returns the second measurement time in milliseconds.
Definition HighPerformanceTimer.h:834
double runningMseconds() const
Returns the current (still) running measurement time in milliseconds.
Definition HighPerformanceTimer.h:947
bool started_
State determining whether one measurement is active currently.
Definition HighPerformanceTimer.h:403
double bestMseconds() const
Returns the best measurement time in milliseconds.
Definition HighPerformanceTimer.h:854
void stopIf(const bool value)
Stops a measurement.
void skipIf(const bool value)
Skips a started measurement.
void start()
Starts a new measurement.
double averageCyclesPerOperation(const double operations, const double clockRate=3800000000.0) const
Returns the average number of CPU cycles needed for one operation.
Definition HighPerformanceTimer.h:909
double last() const
Returns the last measurement time in seconds.
Definition HighPerformanceTimer.h:884
double median() const
Returns the median measurement time in seconds.
double firstMseconds() const
Returns the first measurement time in milliseconds.
Definition HighPerformanceTimer.h:814
double averageMseconds() const
Returns the average measurement time in milliseconds.
Definition HighPerformanceTimer.h:904
double lastMseconds() const
Returns the last (most recent measurement time in milliseconds.
Definition HighPerformanceTimer.h:894
double total() const
Returns the total measurement time in seconds.
Definition HighPerformanceTimer.h:927
double percentile(double value) const
Returns a specific percentile (e.g., P50 = median, P90, P95, etc.) measurement time in seconds.
size_t measurements() const
Returns the number of measurements.
Definition HighPerformanceTimer.h:937
void skip()
Skips a started measurement.
This class implements a high performance timer.
Definition HighPerformanceTimer.h:31
int64_t Ticks
Definition of CPU ticks.
Definition HighPerformanceTimer.h:37
double seconds() const
Returns the measured time since the timer has been started in seconds.
double mseconds() const
Returns the measured time since the timer has been started in milliseconds.
double nseconds() const
Returns the measured time since the timer has been started in nanoseconds.
static Ticks ticksPerSecond()
Returns the resolution of the timer in ticks per second.
static Ticks precision()
Returns the precision of the timer.
double yseconds() const
Returns the measured time since the timer has been started in microseconds.
static Ticks ticks()
Returns the recent CPU ticks.
static double ticks2seconds(const Ticks ticks)
Converts a given CPU tick into seconds regarding the resolution of the timer.
Definition HighPerformanceTimer.h:798
HighPerformanceTimer()
Creates a new timer and starts the time measurement.
void start()
(Re-)starts the time measurement.
Definition HighPerformanceTimer.h:793
This class implements a recursive lock object.
Definition Lock.h:31
This template class is the base class for all singleton objects.
Definition Singleton.h:71
static HighPerformanceBenchmark & get()
Returns a reference to the unique object.
Definition Singleton.h:115
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
std::ostream & operator<<(std::ostream &stream, const HighPerformanceStatistic &highPerformanceStatistic)
Definition HighPerformanceTimer.h:963
uint64_t HighPerformanceTimer_externalPrivacyConfirmTicks()
Returns the recent CPU ticks which will contain a random offset which is constant through the executi...