PerformanceMonitor.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------/*
23 
25 
26 #include <stdlib.h>
27 #include <algorithm>
28 #include <sstream>
29 
30 #include <icl_core/TimeSpan.h>
31 
32 using namespace std;
33 
34 namespace icl_core {
35 namespace perf_mon{
36 
37 string makeName(string prefix, string name)
38 {
39  return prefix + "::" + name;
40 }
41 
42 PerformanceMonitor* PerformanceMonitor::m_instance = NULL;
43 
44 PerformanceMonitor::PerformanceMonitor()
45 {
46  m_enabled = true;
47  m_print_stop = true;
48  m_all_enabled = false;
49 }
50 
51 PerformanceMonitor::~PerformanceMonitor()
52 {
53 
54 }
55 
56 PerformanceMonitor* PerformanceMonitor::getInstance()
57 {
58  if (m_instance == NULL)
59  {
60  m_instance = new PerformanceMonitor();
61  }
62  return m_instance;
63 }
64 
65 void PerformanceMonitor::initialize(const uint32_t num_names, const uint32_t num_events)
66 {
67  PerformanceMonitor* monitor = getInstance();
68  monitor->m_data.clear();
69  monitor->m_data_nontime.clear();
70  monitor->m_buffer.resize(num_names);
71  for (uint32_t i = 0; i < num_names; ++i)
72  monitor->m_buffer[i].reserve(num_events);
73 
74  monitor->enablePrefix("");
75 }
76 
77 
78 bool PerformanceMonitor::isEnabled(string prefix)
79 {
80  return (m_enabled && m_enabled_prefix.find(prefix) != m_enabled_prefix.end()) || m_all_enabled;
81 }
82 
83 void PerformanceMonitor::start(string timer_name)
84 {
85  if (getInstance()->m_enabled)
86  {
87  TimeStamp t = TimeStamp::now();
88  getInstance()->m_timer[timer_name] = t;
89  }
90 }
91 
92 double PerformanceMonitor::measurement(string timer_name, string description, string prefix,
94 {
95  PerformanceMonitor* monitor = getInstance();
96  if (monitor->isEnabled(prefix))
97  {
98  TimeStamp end = TimeStamp::now();
99  TimeSpan d(end - monitor->m_timer[timer_name]);
100  double double_ms = d.toNSec() / 1000000.0;
101  monitor->addEvent(prefix, description, double_ms);
102 
103  if (getInstance()->m_print_stop)
104  {
105  std::stringstream ss;
106  ss << makeName(prefix, description) << ": " << double_ms << " ms";
107  monitor->print(ss.str(), level);
108  }
109  return double_ms;
110  }
111  return 0;
112 }
113 
114 double PerformanceMonitor::startStop(string timer_name, string description, string prefix,
115  logging::LogLevel level)
116 {
117  /*
118  * If timer_name exists:
119  * stop timer
120  * make new start time equal to stop time
121  * else
122  * start timer
123  */
124 
125  if (getInstance()->isEnabled(prefix))
126  {
127  PerformanceMonitor* monitor = getInstance();
128  TimeStamp start = monitor->m_timer[timer_name];
129  if (start != TimeStamp())
130  {
131  TimeStamp end = TimeStamp::now();
132  TimeSpan d(end - start);
133  double double_ms = d.toNSec() / 1000000.0;
134  monitor->addEvent(prefix, description, double_ms);
135  monitor->m_timer[timer_name] = end;
136  if (getInstance()->m_print_stop)
137  {
138  std::stringstream ss;
139  ss << makeName(prefix, description) << ": " << double_ms << " ms";
140  monitor->print(ss.str(), level);
141  }
142  return double_ms;
143  }
144  else
145  {
146  PerformanceMonitor::start(timer_name);
147  }
148  }
149  return 0;
150 }
151 
152 void PerformanceMonitor::addStaticData(string name, double data, string prefix)
153 {
154  if (getInstance()->isEnabled(prefix))
155  {
156  string tmp = makeName(prefix, name);
157  getInstance()->m_static_data[tmp] = data;
158  }
159 }
160 
161 void PerformanceMonitor::addData(string name, double data, string prefix)
162 {
163  if (getInstance()->isEnabled(prefix))
164  {
165  getInstance()->addEvent(prefix, name, data);
166  }
167 }
168 
169 void PerformanceMonitor::addNonTimeData(string name, double data, string prefix)
170 {
171  if (getInstance()->isEnabled(prefix))
172  {
173  getInstance()->addNonTimeEvent(prefix, name, data);
174  }
175 }
176 
177 void PerformanceMonitor::addEvent(string prefix, string name, double data)
178 {
179  if (getInstance()->isEnabled(prefix))
180  {
181  string tmp = makeName(prefix, name);
182  if (m_data.find(tmp) == m_data.end())
183  {
184  m_data[tmp] = vector<double>();
185  if (m_buffer.size() > 0)
186  {
187  m_data[tmp].swap(m_buffer.back());
188  m_buffer.pop_back();
189  }
190  }
191  m_data[tmp].push_back(data);
192  }
193 }
194 
195 void PerformanceMonitor::addNonTimeEvent(string prefix, string name, double data)
196 {
197  if (getInstance()->isEnabled(prefix))
198  {
199  string tmp = makeName(prefix, name);
200  if (m_data_nontime.find(tmp) == m_data_nontime.end())
201  {
202  m_data_nontime[tmp] = vector<double>();
203  if (m_buffer.size() > 0)
204  {
205  m_data_nontime[tmp].swap(m_buffer.back());
206  m_buffer.pop_back();
207  }
208  }
209  m_data_nontime[tmp].push_back(data);
210  }
211 }
212 
213 
214 void PerformanceMonitor::print(string message, logging::LogLevel level)
215 {
216  switch (level)
217  {
219  {
220  LOGGING_DEBUG(Performance, message << endl);
221  break;
222  }
224  {
225  LOGGING_INFO(Performance, message << endl);
226  break;
227  }
229  {
230  LOGGING_TRACE(Performance, message << endl);
231  break;
232  }
233  default:
234  {
235  LOGGING_INFO(Performance, message << endl);
236  break;
237  }
238  }
239 }
240 
241 void PerformanceMonitor::createStatisticSummary(stringstream& ss, string prefix, string name)
242 {
243  string tmp = makeName(prefix, name);
244  double median, min, max;
245  getMedian(tmp, median, min, max);
246 
247  ss << "Summary for " << tmp << "\n" <<
248  "Called " << m_data[tmp].size() << " times\n" <<
249  name << "_avg: " << getAverage(tmp) << " ms\n" <<
250  name << "_median: " << median << " ms\n" <<
251  name << "_min: " << min << " ms\n" <<
252  name << "_max: " << max << " ms\n"<<
253  "\n";
254 }
255 
256 void PerformanceMonitor::createStatisticSummaryNonTime(stringstream& ss, string prefix, string name)
257 {
258  string tmp = makeName(prefix, name);
259  double median, min, max;
260  getMedianNonTime(tmp, median, min, max);
261 
262  ss << "Summary for " << tmp << "\n" <<
263  "num entries: " << m_data_nontime[tmp].size() << "\n" <<
264  name << "_avg: " << getAverageNonTime(tmp) << "\n" <<
265  name << "_median: " << median << "\n" <<
266  name << "_min: " << min << "\n" <<
267  name << "_max: " << max << "\n"<<
268  "\n";
269 }
270 
271 void PerformanceMonitor::printSummary(string prefix, string name,
273 {
274  PerformanceMonitor* monitor = getInstance();
275 
276  std::stringstream ss;
277  monitor->createStatisticSummary(ss, prefix, name);
278  monitor->print(ss.str(), level);
279 }
280 
281 void PerformanceMonitor::enablePrefix(string prefix)
282 {
283  PerformanceMonitor* monitor = getInstance();
284 
285  if (monitor->m_enabled_prefix.find(prefix) == monitor->m_enabled_prefix.end())
286  {
287  monitor->m_enabled_prefix[prefix] = true;
288  }
289 }
290 
291 void PerformanceMonitor::enableAll(const bool& enabled)
292 {
293  getInstance()->m_all_enabled = enabled;
294 }
295 
296 void PerformanceMonitor::disablePrefix(string prefix)
297 {
298  PerformanceMonitor* monitor = getInstance();
299 
300  if (monitor->m_enabled_prefix.find(prefix) != monitor->m_enabled_prefix.end())
301  {
302  monitor->m_enabled_prefix.erase(prefix);
303  }
304 }
305 
306 void PerformanceMonitor::printSummaryAll(icl_core::logging::LogLevel level)
307 {
308  PerformanceMonitor* monitor = getInstance();
309 
310  for (map<string, bool>::iterator it=monitor->m_enabled_prefix.begin();
311  it != monitor->m_enabled_prefix.end(); ++it)
312  {
313  printSummaryFromPrefix(it->first, level);
314  }
315 }
316 
317 void PerformanceMonitor::printSummaryFromPrefix(string prefix, icl_core::logging::LogLevel level)
318 {
319  PerformanceMonitor* monitor = getInstance();
320  bool first = true;
321  std::stringstream ss;
322  ss << "\n########## Begin of Summary for prefix " << prefix << " ##########\n";
323  for (map<string, double>::iterator it = monitor->m_static_data.begin(); it != monitor->m_static_data.end(); it++)
324  {
325  size_t prefix_end = it->first.find("::");
326  std::string prefix_tmp = it->first.substr(0, prefix_end);
327 
328  if (prefix == prefix_tmp)
329  {
330  if (first)
331  {
332  ss << "#### Static data: ####\n";
333  first = false;
334  }
335  ss << it->first.substr(prefix_end+2) << ": " << it->second << "\n";
336  }
337  }
338 
339  first = true;
340  for (map<string, vector<double> >::iterator it = monitor->m_data.begin(); it != monitor->m_data.end(); it++)
341  {
342  size_t prefix_end = it->first.find("::");
343  std::string prefix_tmp = it->first.substr(0, prefix_end);
344 
345  if (prefix == prefix_tmp)
346  {
347  if (first)
348  {
349  ss << "#### Time data: ####\n";
350  first = false;
351  }
352  string name = it->first.substr(prefix_end+2);
353  monitor->createStatisticSummary(ss, prefix, name);
354  }
355  }
356 
357  first = true;
358  for (map<string, vector<double> >::iterator it = monitor->m_data_nontime.begin(); it != monitor->m_data_nontime.end(); it++)
359  {
360  size_t prefix_end = it->first.find("::");
361  std::string prefix_tmp = it->first.substr(0, prefix_end);
362 
363  if (prefix == prefix_tmp)
364  {
365  if (first)
366  {
367  ss << "#### Non-time data: ####\n";
368  first = false;
369  }
370  string name = it->first.substr(prefix_end+2);
371  monitor->createStatisticSummaryNonTime(ss, prefix, name);
372  }
373  }
374  monitor->print(ss.str(), level);
375 }
376 
377 double PerformanceMonitor::getAverage(string name)
378 {
379  double avg=0;
380  vector<double>* tmp = &m_data[name];
381  int n = (int) m_data[name].size();
382  for (int i = 0; i < n; ++i)
383  avg = avg + tmp->at(i);
384  avg = avg / n;
385  return avg;
386 }
387 
388 double PerformanceMonitor::getAverageNonTime(string name)
389 {
390  double avg=0;
391  vector<double>* tmp = &m_data_nontime[name];
392  int n = (int) m_data_nontime[name].size();
393  for (int i = 0; i < n; ++i)
394  avg = avg + tmp->at(i);
395  avg = avg / n;
396  return avg;
397 }
398 
399 void PerformanceMonitor::getMedian(string name, double& median, double& min, double& max)
400 {
401  vector<double> tmp = m_data[name];
402  sort(tmp.begin(), tmp.end());
403  median = tmp[tmp.size() / 2];
404  min = tmp[0];
405  max = tmp[tmp.size() - 1];
406 }
407 
408 void PerformanceMonitor::getMedianNonTime(string name, double& median, double& min, double& max)
409 {
410  vector<double> tmp = m_data_nontime[name];
411  sort(tmp.begin(), tmp.end());
412  if (tmp.size() > 0)
413  median = tmp[tmp.size() / 2];
414  min = tmp[0];
415  max = tmp[tmp.size() - 1];
416 }
417 
418 } // namespace timer
419 } // namespace icl_core
420 
void print(std::string message, icl_core::logging::LogLevel level=icl_core::logging::eLL_DEBUG)
prints the given message to the specified log level
unsigned int uint32_t
Definition: msvc_stdint.h:93
Represents absolute times.
Definition: TimeStamp.h:61
void createStatisticSummaryNonTime(std::stringstream &ss, std::string prefix, std::string name)
bool initialize(int &argc, char *argv[], bool remove_read_arguments)
Definition: Config.cpp:50
std::map< std::string, double > m_static_data
#define LOGGING_INFO(streamname, arg)
#define LOGGING_DEBUG(streamname, arg)
void addEvent(std::string prefix, std::string name, double data)
add event to the event map
The PerformanceMonitor class provides an easy to use tool for performance measurement.
std::map< std::string, TimeStamp > m_timer
std::vector< std::vector< double > > m_buffer
std::map< std::string, bool > m_enabled_prefix
int64_t toNSec() const
Definition: TimeSpan.cpp:173
string makeName(string prefix, string name)
ThreadStream & endl(ThreadStream &stream)
Definition: ThreadStream.h:249
void createStatisticSummary(std::stringstream &ss, std::string prefix, std::string name)
Create output string for summary.
static void enablePrefix(std::string prefix)
enablePrefix Enables a given prefix
Repesents absolute times.
Definition: TimeSpan.h:46
bool isEnabled(std::string prefix)
check if prefix is enabled
std::map< std::string, std::vector< double > > m_data_nontime
std::map< std::string, std::vector< double > > m_data
#define LOGGING_TRACE(streamname, arg)


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58