SPH
Profiler.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "io/Logger.h"
10 #include "system/Platform.h"
11 #include "system/Timer.h"
12 #include <atomic>
13 #include <map>
14 #include <thread>
15 
17 
22 struct ScopedTimer {
23 private:
24  StoppableTimer impl;
25  std::string name;
26 
27  using OnScopeEnds = std::function<void(const std::string&, const uint64_t)>;
28  OnScopeEnds callback;
29 
30 public:
35  ScopedTimer(const std::string& name, const OnScopeEnds& callback)
36  : name(name)
37  , callback(callback) {}
38 
40  callback(name, impl.elapsed(TimerUnit::MICROSECOND));
41  }
42 
43  void stop() {
44  impl.stop();
45  }
46 
47  void resume() {
48  impl.resume();
49  }
50 
51  void next(const std::string& newName) {
52  callback(name, impl.elapsed(TimerUnit::MICROSECOND));
53  impl.restart();
54  name = newName;
55  }
56 };
57 
58 #ifdef SPH_PROFILE
59 #define MEASURE_SCOPE(name) \
60  ScopedTimer __timer("", [](const std::string&, const uint64_t time) { \
61  StdOutLogger logger; \
62  logger.write(name, " took ", time / 1000, " ms"); \
63  });
64 #define MEASURE(name, what) \
65  { \
66  MEASURE_SCOPE(name); \
67  what; \
68  }
69 #else
70 #define MEASURE_SCOPE(name)
71 #define MEASURE(name, what) what
72 #endif
73 
74 #ifdef SPH_PROFILE
75 
76 struct ScopeStatistics {
78  std::string name;
79 
81  uint64_t totalTime;
82 
85  Float relativeTime;
86 
87  Float cpuUsage;
88 };
89 
90 
92 class Profiler : public Noncopyable {
93 private:
94  static AutoPtr<Profiler> instance;
95 
96  struct ScopeRecord {
98  std::atomic<uint64_t> duration{ 0 };
99 
101  Float cpuUsage = 0._f;
102 
104  Size weight = 0;
105  };
106 
107  // map of profiled scopes, its key being a string = name of the scope
108  std::map<std::string, ScopeRecord> records;
109 
110  struct {
111  std::string currentScope;
112  std::thread thread;
113  } cpuUsage;
114 
115  std::atomic_bool quitting{ false };
116 
117 public:
118  Profiler() {
119  cpuUsage.thread = std::thread([this] {
120  while (!quitting) {
121  const Optional<Float> usage = getCpuUsage();
122  if (usage && !cpuUsage.currentScope.empty()) {
123  ScopeRecord& scope = records[cpuUsage.currentScope];
124  scope.cpuUsage = (scope.cpuUsage * scope.weight + usage.value()) / (scope.weight + 1);
125  scope.weight++;
126  }
127  std::this_thread::sleep_for(std::chrono::milliseconds(20));
128  }
129  });
130  }
131 
132  ~Profiler() {
133  quitting = true;
134  cpuUsage.thread.join();
135  }
136 
137  static Profiler& getInstance() {
138  if (!instance) {
139  instance = makeAuto<Profiler>();
140  }
141  return *instance;
142  }
143 
147  ScopedTimer makeScopedTimer(const std::string& name) {
148  cpuUsage.currentScope = name;
149  return ScopedTimer(name, [this](const std::string& n, const uint64_t elapsed) { //
150  records[n].duration += elapsed;
151  });
152  }
153 
155  Array<ScopeStatistics> getStatistics() const;
156 
158  void printStatistics(ILogger& logger) const;
159 
161  void clear() {
162  records.clear();
163  }
164 };
165 
166 #define PROFILE_SCOPE(name) \
167  Profiler& __instance = Profiler::getInstance(); \
168  ScopedTimer __scopedTimer = __instance.makeScopedTimer(name);
169 #define PROFILE(name, what) \
170  { \
171  PROFILE_SCOPE(name); \
172  what; \
173  }
174 #else
175 #define PROFILE_SCOPE(name)
176 #define PROFILE(name, what) what
177 #endif
178 
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Logging routines of the run.
INLINE Float weight(const Vector &r1, const Vector &r2)
#define NAMESPACE_SPH_END
Definition: Object.h:12
Wrapper of type value of which may or may not be present.
Optional< Float > getCpuUsage()
Definition: Platform.cpp:144
System functions.
Measuring time intervals and executing periodic events.
Generic dynamically allocated resizable storage.
Definition: Array.h:43
Wrapper of pointer that deletes the resource from destructor.
Definition: AutoPtr.h:15
Interface providing generic (text, human readable) output of the program.
Definition: Logger.h:22
INLINE Type & value()
Returns the reference to the stored value.
Definition: Optional.h:172
Simple extension of Timer allowing to pause and continue timer.
Definition: Timer.h:72
int64_t elapsed(const TimerUnit unit) const
Returns elapsed time in timer units. Does not reset the timer.
Definition: Timer.cpp:85
void stop()
Stops the timer. Function getElapsed() will report the same value from now on.
Definition: Timer.cpp:70
void resume()
Resumes stopped timer.
Definition: Timer.cpp:77
void restart()
Reset elapsed duration to zero.
Definition: Timer.cpp:51
Object with deleted copy constructor and copy operator.
Definition: Object.h:54
Timer that reports the measured duration when being destroyed.
Definition: Profiler.h:22
~ScopedTimer()
Definition: Profiler.h:39
void resume()
Definition: Profiler.h:47
void next(const std::string &newName)
Definition: Profiler.h:51
void stop()
Definition: Profiler.h:43
ScopedTimer(const std::string &name, const OnScopeEnds &callback)
Definition: Profiler.h:35