Profiler.h
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 
36 /* Author Ioan Sucan */
37 
38 #ifndef OMPL_TOOLS_DEBUG_PROFILER_
39 #define OMPL_TOOLS_DEBUG_PROFILER_
40 
41 #ifndef ENABLE_PROFILING
42 
46 # ifdef NDEBUG
47 # define ENABLE_PROFILING 0
48 # else
49 # define ENABLE_PROFILING 1
50 # endif
51 
52 #endif
53 
54 #if ENABLE_PROFILING
55 
56 #include <map>
57 #include <string>
58 #include <iostream>
59 #include <thread>
60 #include <mutex>
61 
62 #include "ompl/util/Time.h"
63 
64 namespace ompl
65 {
66 
67  namespace tools
68  {
69 
75  class Profiler
76  {
77  public:
78  // non-copyable
79  Profiler(const Profiler&) = delete;
80  Profiler& operator=(const Profiler&) = delete;
81 
84  {
85  public:
87  ScopedBlock(const std::string &name, Profiler &prof = Profiler::Instance()) : name_(name), prof_(prof)
88  {
89  prof_.begin(name);
90  }
91 
92  ~ScopedBlock()
93  {
94  prof_.end(name_);
95  }
96 
97  private:
98 
99  std::string name_;
100  Profiler &prof_;
101  };
102 
106  {
107  public:
108 
110  ScopedStart(Profiler &prof = Profiler::Instance()) : prof_(prof), wasRunning_(prof_.running())
111  {
112  if (!wasRunning_)
113  prof_.start();
114  }
115 
116  ~ScopedStart()
117  {
118  if (!wasRunning_)
119  prof_.stop();
120  }
121 
122  private:
123 
124  Profiler &prof_;
125  bool wasRunning_;
126  };
127 
129  static Profiler& Instance();
130 
133  Profiler(bool printOnDestroy = false, bool autoStart = false) : running_(false), printOnDestroy_(printOnDestroy)
134  {
135  if (autoStart)
136  start();
137  }
138 
141  {
142  if (printOnDestroy_ && !data_.empty())
143  status();
144  }
145 
147  static void Start()
148  {
149  Instance().start();
150  }
151 
153  static void Stop()
154  {
155  Instance().stop();
156  }
157 
159  static void Clear()
160  {
161  Instance().clear();
162  }
163 
165  void start();
166 
168  void stop();
169 
171  void clear();
172 
174  static void Event(const std::string& name, const unsigned int times = 1)
175  {
176  Instance().event(name, times);
177  }
178 
180  void event(const std::string &name, const unsigned int times = 1);
181 
183  static void Average(const std::string& name, const double value)
184  {
185  Instance().average(name, value);
186  }
187 
189  void average(const std::string &name, const double value);
190 
192  static void Begin(const std::string &name)
193  {
194  Instance().begin(name);
195  }
196 
198  static void End(const std::string &name)
199  {
200  Instance().end(name);
201  }
202 
204  void begin(const std::string &name);
205 
207  void end(const std::string &name);
208 
212  static void Status(std::ostream &out = std::cout, bool merge = true)
213  {
214  Instance().status(out, merge);
215  }
216 
220  void status(std::ostream &out = std::cout, bool merge = true);
221 
224  static void Console()
225  {
226  Instance().console();
227  }
228 
231  void console();
232 
234  bool running() const
235  {
236  return running_;
237  }
238 
240  static bool Running()
241  {
242  return Instance().running();
243  }
244 
245  private:
246 
248  struct TimeInfo
249  {
250  TimeInfo() : total(time::seconds(0.)), shortest(time::duration::max()), longest(time::duration::min()), parts(0)
251  {
252  }
253 
255  time::duration total;
256 
258  time::duration shortest;
259 
261  time::duration longest;
262 
264  unsigned long int parts;
265 
268 
270  void set()
271  {
272  start = time::now();
273  }
274 
276  void update()
277  {
278  const time::duration &dt = time::now() - start;
279  if (dt > longest)
280  longest = dt;
281  if (dt < shortest)
282  shortest = dt;
283  total = total + dt;
284  ++parts;
285  }
286  };
287 
289  struct AvgInfo
290  {
292  double total;
293 
295  double totalSqr;
296 
298  unsigned long int parts;
299  };
300 
302  struct PerThread
303  {
305  std::map<std::string, unsigned long int> events;
306 
308  std::map<std::string, AvgInfo> avg;
309 
311  std::map<std::string, TimeInfo> time;
312  };
313 
314  void printThreadInfo(std::ostream &out, const PerThread &data);
315 
316  std::mutex lock_;
317  std::map<std::thread::id, PerThread> data_;
318  TimeInfo tinfo_;
319  bool running_;
320  bool printOnDestroy_;
321 
322  };
323  }
324 }
325 
326 #else
327 
328 #include <string>
329 #include <iostream>
330 
331 /* If profiling is disabled, provide empty implementations for the
332  public functions */
333 namespace ompl
334 {
335 
336  namespace tools
337  {
338 
339  class Profiler
340  {
341  public:
342 
343  class ScopedBlock
344  {
345  public:
346 
347  ScopedBlock(const std::string &, Profiler & = Profiler::Instance())
348  {
349  }
350 
351  ~ScopedBlock()
352  {
353  }
354  };
355 
356  class ScopedStart
357  {
358  public:
359 
360  ScopedStart(Profiler & = Profiler::Instance())
361  {
362  }
363 
364  ~ScopedStart()
365  {
366  }
367  };
368 
369  static Profiler& Instance();
370 
371  Profiler(bool = true, bool = true)
372  {
373  }
374 
375  ~Profiler()
376  {
377  }
378 
379  static void Start()
380  {
381  }
382 
383  static void Stop()
384  {
385  }
386 
387  static void Clear()
388  {
389  }
390 
391  void start()
392  {
393  }
394 
395  void stop()
396  {
397  }
398 
399  void clear()
400  {
401  }
402 
403  static void Event(const std::string&, const unsigned int = 1)
404  {
405  }
406 
407  void event(const std::string &, const unsigned int = 1)
408  {
409  }
410 
411  static void Average(const std::string&, const double)
412  {
413  }
414 
415  void average(const std::string &, const double)
416  {
417  }
418 
419  static void Begin(const std::string &)
420  {
421  }
422 
423  static void End(const std::string &)
424  {
425  }
426 
427  void begin(const std::string &)
428  {
429  }
430 
431  void end(const std::string &)
432  {
433  }
434 
435  static void Status(std::ostream & = std::cout, bool = true)
436  {
437  }
438 
439  void status(std::ostream & = std::cout, bool = true)
440  {
441  }
442 
443  static void Console()
444  {
445  }
446 
447  void console()
448  {
449  }
450 
451  bool running() const
452  {
453  return false;
454  }
455 
456  static bool Running()
457  {
458  return false;
459  }
460  };
461  }
462 }
463 
464 #endif
465 
466 #endif
static void Stop()
Stop counting time.
Definition: Profiler.h:153
bool running() const
Check if the profiler is counting time or not.
Definition: Profiler.h:234
void stop()
Stop counting time.
static void Event(const std::string &name, const unsigned int times=1)
Count a specific event for a number of times.
Definition: Profiler.h:174
static void Average(const std::string &name, const double value)
Maintain the average of a specific value.
Definition: Profiler.h:183
static void End(const std::string &name)
Stop counting time for a specific chunk of code.
Definition: Profiler.h:198
void begin(const std::string &name)
Begin counting time for a specific chunk of code.
void start()
Start counting time.
static bool Running()
Check if the profiler is counting time or not.
Definition: Profiler.h:240
void end(const std::string &name)
Stop counting time for a specific chunk of code.
void status(std::ostream &out=std::cout, bool merge=true)
Print the status of the profiled code chunks and events. Optionally, computation done by different th...
void event(const std::string &name, const unsigned int times=1)
Count a specific event for a number of times.
Profiler(bool printOnDestroy=false, bool autoStart=false)
Constructor. It is allowed to separately instantiate this class (not only as a singleton) ...
Definition: Profiler.h:133
static void Console()
Print the status of the profiled code chunks and events to the console (using msg::Console) ...
Definition: Profiler.h:224
ScopedBlock(const std::string &name, Profiler &prof=Profiler::Instance())
Start counting time for the block named name of the profiler prof.
Definition: Profiler.h:87
std::chrono::system_clock::duration duration
Representation of a time duration.
Definition: Time.h:69
static void Status(std::ostream &out=std::cout, bool merge=true)
Print the status of the profiled code chunks and events. Optionally, computation done by different th...
Definition: Profiler.h:212
static void Begin(const std::string &name)
Begin counting time for a specific chunk of code.
Definition: Profiler.h:192
This is a simple thread-safe tool for counting time spent in various chunks of code. This is different from external profiling tools in that it allows the user to count time spent in various bits of code (sub-function granularity) or count how many times certain pieces of code are executed.
Definition: Profiler.h:75
void console()
Print the status of the profiled code chunks and events to the console (using msg::Console) ...
This instance will call Profiler::start() when constructed and Profiler::stop() when it goes out of s...
Definition: Profiler.h:105
point now()
Get the current time point.
Definition: Time.h:72
void clear()
Clear counted time and events.
static void Start()
Start counting time.
Definition: Profiler.h:147
~Profiler()
Destructor.
Definition: Profiler.h:140
static void Clear()
Clear counted time and events.
Definition: Profiler.h:159
static Profiler & Instance()
Return an instance of the class.
Definition: Profiler.cpp:41
void average(const std::string &name, const double value)
Maintain the average of a specific value.
std::chrono::system_clock::time_point point
Representation of a point in time.
Definition: Time.h:66
This instance will call Profiler::begin() when constructed and Profiler::end() when it goes out of sc...
Definition: Profiler.h:83
ScopedStart(Profiler &prof=Profiler::Instance())
Take as argument the profiler instance to operate on (prof)
Definition: Profiler.h:110