Overte C++ Documentation
PerfStat.h
1 //
2 // PerfStat.h
3 // libraries/shared/src
4 //
5 // Created by Brad Hefta-Gaub on 3/29/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Poor-man's performance stats collector class. Useful for collecting timing
9 // details from various portions of the code.
10 //
11 // Distributed under the Apache License, Version 2.0.
12 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
13 //
14 
15 #ifndef hifi_PerfStat_h
16 #define hifi_PerfStat_h
17 
18 #include <stdint.h>
19 #include "SharedUtil.h"
20 #include "SimpleMovingAverage.h"
21 
22 #include <atomic>
23 #include <cstring>
24 #include <string>
25 #include <map>
26 
27 using AtomicUIntStat = std::atomic<uintmax_t>;
28 
29 class PerformanceWarning {
30 private:
31  quint64 _start;
32  const char* _message;
33  bool _renderWarningsOn;
34  bool _alwaysDisplay;
35  AtomicUIntStat* _runningTotal;
36  AtomicUIntStat* _totalCalls;
37  static bool _suppressShortTimings;
38 public:
39 
40  PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false,
41  AtomicUIntStat* runningTotal = NULL, AtomicUIntStat* totalCalls = NULL) :
42  _start(usecTimestampNow()),
43  _message(message),
44  _renderWarningsOn(renderWarnings),
45  _alwaysDisplay(alwaysDisplay),
46  _runningTotal(runningTotal),
47  _totalCalls(totalCalls) { }
48 
49  quint64 elapsed() const { return (usecTimestampNow() - _start); };
50 
51  ~PerformanceWarning();
52 
53  static void setSuppressShortTimings(bool suppressShortTimings) { _suppressShortTimings = suppressShortTimings; }
54 };
55 
56 class PerformanceTimerRecord {
57 public:
58  PerformanceTimerRecord() : _runningTotal(0), _lastTotal(0), _numAccumulations(0), _numTallies(0), _expiry(0) {}
59 
60  void accumulateResult(const quint64& elapsed) { _runningTotal += elapsed; ++_numAccumulations; }
61  void tallyResult(const quint64& now);
62  bool isStale(const quint64& now) const { return now > _expiry; }
63  quint64 getAverage() const { return (_numTallies == 0) ? 0 : _runningTotal / _numTallies; }
64  quint64 getMovingAverage() const { return (_numTallies == 0) ? 0 : _movingAverage.getAverage(); }
65  quint64 getCount() const { return _numTallies; }
66 
67 private:
68  quint64 _runningTotal;
69  quint64 _lastTotal;
70  quint64 _numAccumulations;
71  quint64 _numTallies;
72  quint64 _expiry;
73  SimpleMovingAverage _movingAverage;
74 };
75 
76 class PerformanceTimer {
77 public:
78 
79  PerformanceTimer(const QString& name);
80  ~PerformanceTimer();
81 
82  static bool isActive();
83  static void setActive(bool active);
84 
85  static QString getContextName();
86  static void addTimerRecord(const QString& fullName, quint64 elapsedUsec);
87  static QMap<QString, PerformanceTimerRecord> getAllTimerRecords();
88  static void tallyAllTimerRecords();
89  static void dumpAllTimerRecords();
90 
91 private:
92  quint64 _start = 0;
93  QString _name;
94  static std::atomic<bool> _isActive;
95 
96  static std::mutex _mutex; // used to guard multi-threaded access to _fullNames and _records
97  static QHash<QThread*, QString> _fullNames;
98  static QMap<QString, PerformanceTimerRecord> _records;
99 };
100 
101 // uncomment WANT_DETAILED_PERFORMANCE_TIMERS definition to enable performance timers in high-frequency contexts
102 //#define WANT_DETAILED_PERFORMANCE_TIMERS
103 #ifdef WANT_DETAILED_PERFORMANCE_TIMERS
104  #define DETAILED_PERFORMANCE_TIMER(name) PerformanceTimer detailedPerformanceTimer(name);
105 #else // WANT_DETAILED_PERFORMANCE_TIMERS
106  #define DETAILED_PERFORMANCE_TIMER(name) ; // no-op
107 #endif // WANT_DETAILED_PERFORMANCE_TIMERS
108 
109 #endif // hifi_PerfStat_h