tudocomp
– The TU Dortmund Compression Framework
StatPhase.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstring>
4 #include <ctime>
5 #include <string>
6 
7 #include <tudocomp_stat/Json.hpp>
8 
9 #ifndef STATS_DISABLED
10 
12 
13 #include <time.h>
14 #include <sys/time.h>
15 
16 #ifdef __MACH__
17 #include <mach/clock.h>
18 #include <mach/mach.h>
19 #endif
20 
21 namespace tdc {
22 
23 // Use clock_gettime in linux, clock_get_time in OS X.
24 inline void get_monotonic_time(struct timespec *ts){
25 #ifdef __MACH__
26  clock_serv_t cclock;
27  mach_timespec_t mts;
28  host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
29  clock_get_time(cclock, &mts);
30  mach_port_deallocate(mach_task_self(), cclock);
31  ts->tv_sec = mts.tv_sec;
32  ts->tv_nsec = mts.tv_nsec;
33 #else
34  clock_gettime(CLOCK_MONOTONIC, ts);
35 #endif
36 }
37 
44 class StatPhase {
45 private:
46  static StatPhase* s_current;
47 
48  inline static unsigned long current_time_millis() {
49  timespec t;
51 
52  return t.tv_sec * 1000L + t.tv_nsec / 1000000L;
53  }
54 
55  StatPhase* m_parent = nullptr;
56  PhaseData* m_data = nullptr;
57 
58  bool m_track_memory = false;
59  bool m_disabled = false;
60 
61  inline void append_child(PhaseData* data) {
62  if(m_data->first_child) {
63  PhaseData* last = m_data->first_child;
64  while(last->next_sibling) {
65  last = last->next_sibling;
66  }
67  last->next_sibling = data;
68  } else {
69  m_data->first_child = data;
70  }
71  }
72 
73  inline void track_alloc_internal(size_t bytes) {
74  if(m_track_memory) {
75  m_data->mem_current += bytes;
76  m_data->mem_peak = std::max(m_data->mem_peak, m_data->mem_current);
77  if(m_parent) m_parent->track_alloc_internal(bytes);
78  }
79  }
80 
81  inline void track_free_internal(size_t bytes) {
82  if(m_track_memory) {
83  m_data->mem_current -= bytes;
84  if(m_parent) m_parent->track_free_internal(bytes);
85  }
86  }
87 
88  inline void pause() {
89  m_track_memory = false;
90  }
91 
92  inline void resume() {
93  m_track_memory = true;
94  }
95 
96  inline void init(const char* title) {
97  m_parent = s_current;
98 
99  if(m_parent) m_parent->pause();
100  m_data = new PhaseData();
101  if(m_parent) m_parent->resume();
102  m_data->title(title);
103 
104  m_data->mem_off = m_parent ? m_parent->m_data->mem_current : 0;
105  m_data->mem_current = 0;
106  m_data->mem_peak = 0;
107 
108  m_data->time_end = 0;
109  m_data->time_start = current_time_millis();
110 
111  s_current = this;
112  }
113 
114  inline void finish() {
115  m_data->time_end = current_time_millis();
116 
117  if(m_parent) {
118  // add data to parent's data
119  m_parent->append_child(m_data);
120  } else {
121  // if this was the root, delete data
122  delete m_data;
123  m_data = nullptr;
124  }
125 
126  // pop parent
127  s_current = m_parent;
128  }
129 
130 public:
142  template<typename F>
143  inline static auto wrap(const char* title, F func) ->
144  typename std::result_of<F(StatPhase&)>::type {
145 
146  StatPhase phase(title);
147  return func(phase);
148  }
149 
161  template<typename F>
162  inline static auto wrap(const char* title, F func) ->
163  typename std::result_of<F()>::type {
164 
165  StatPhase phase(title);
166  return func();
167  }
168 
178  inline static void track_alloc(size_t bytes) {
179  if(s_current) s_current->track_alloc_internal(bytes);
180  }
181 
190  inline static void track_free(size_t bytes) {
191  if(s_current) s_current->track_free_internal(bytes);
192  }
193 
198  inline static void pause_tracking() {
199  if(s_current) s_current->pause();
200  }
201 
206  inline static void resume_tracking() {
207  if(s_current) s_current->resume();
208  }
209 
217  template<typename T>
218  inline static void log(const char* key, const T& value) {
219  if(s_current) s_current->log_stat(key, value);
220  }
221 
223  inline StatPhase() {
224  m_disabled = true;
225  }
226 
233  inline StatPhase(const char* title) {
234  pause();
235  init(title);
236  resume();
237  }
238 
245  inline StatPhase(const std::string& str) : StatPhase(str.c_str()) {
246  }
247 
251  inline ~StatPhase() {
252  if (!m_disabled) {
253  pause();
254  finish();
255  }
256  }
257 
264  inline void split(const char* new_title) {
265  if (!m_disabled) {
266  pause();
267 
268  finish();
269  PhaseData* old_data = m_data;
270 
271  init(new_title);
272  if(old_data) {
273  m_data->mem_off = old_data->mem_off + old_data->mem_current;
274  }
275 
276  resume();
277  }
278  }
279 
286  inline void split(const std::string& new_title) {
287  split(new_title.c_str());
288  }
289 
297  template<typename T>
298  inline void log_stat(const char* key, const T& value) {
299  if (!m_disabled) {
300  pause();
301  m_data->log_stat(key, value);
302  resume();
303  }
304  }
305 
312  if (!m_disabled) {
313  m_data->time_end = current_time_millis();
314  pause();
315  json::Object obj = m_data->to_json();
316  resume();
317  return obj;
318  } else {
319  return json::Object();
320  }
321  }
322 };
323 
324 }
325 
326 #else
327 
329 
330 namespace tdc {
331 
332  using StatPhase = StatPhaseDummy;
333 
334 }
335 
336 #endif
337 
Contains the text compression and encoding framework.
Definition: namespaces.hpp:11
void split(const std::string &new_title)
Starts a new phase as a sibling, reusing the same object.
Definition: StatPhase.hpp:286
static void track_free(size_t bytes)
Tracks a memory deallocation of the given size for the current phase.
Definition: StatPhase.hpp:190
StatPhase(const std::string &str)
Creates a new statistics phase.
Definition: StatPhase.hpp:245
static void pause_tracking()
Pauses the tracking of memory allocations in the current phase.
Definition: StatPhase.hpp:198
StatPhase()
Creates a inert statistics phase without any effect.
Definition: StatPhase.hpp:223
Provides access to runtime and memory measurement in statistics phases.
Definition: StatPhase.hpp:44
StatPhase(const char *title)
Creates a new statistics phase.
Definition: StatPhase.hpp:233
void split(const char *new_title)
Starts a new phase as a sibling, reusing the same object.
Definition: StatPhase.hpp:264
json::Object to_json()
Constructs the JSON representation of the measured data.
Definition: StatPhase.hpp:311
~StatPhase()
Destroys and ends the phase.
Definition: StatPhase.hpp:251
Represents a JSON object that behaves like a dictionary.
Definition: Json.hpp:153
void log_stat(const char *key, const T &value)
Logs a user statistic for this phase.
Definition: StatPhase.hpp:298
static void log(const char *key, const T &value)
Logs a user statistic for the current phase.
Definition: StatPhase.hpp:218
void get_monotonic_time(struct timespec *ts)
Definition: StatPhase.hpp:24
static auto wrap(const char *title, F func) -> typename std::result_of< F(StatPhase &)>::type
Executes a lambda as a single statistics phase.
Definition: StatPhase.hpp:143
static void resume_tracking()
Resumes the tracking of memory allocations in the current phase.
Definition: StatPhase.hpp:206
static void track_alloc(size_t bytes)
Tracks a memory allocation of the given size for the current phase.
Definition: StatPhase.hpp:178
static auto wrap(const char *title, F func) -> typename std::result_of< F()>::type
Executes a lambda as a single statistics phase.
Definition: StatPhase.hpp:162