ompl/tools/debug/Profiler.h
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2008, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00035 00036 /* Author Ioan Sucan */ 00037 00038 #ifndef OMPL_TOOLS_DEBUG_PROFILER_ 00039 #define OMPL_TOOLS_DEBUG_PROFILER_ 00040 00041 #define ENABLE_PROFILING 1 00042 00043 #ifndef ENABLE_PROFILING 00044 00048 # ifdef NDEBUG 00049 # define ENABLE_PROFILING 0 00050 # else 00051 # define ENABLE_PROFILING 1 00052 # endif 00053 00054 #endif 00055 00056 #if ENABLE_PROFILING 00057 00058 #include <map> 00059 #include <string> 00060 #include <iostream> 00061 #include <boost/thread.hpp> 00062 #include <boost/noncopyable.hpp> 00063 00064 #include "ompl/util/Time.h" 00065 00066 namespace ompl 00067 { 00068 00069 namespace tools 00070 { 00071 00077 class Profiler : private boost::noncopyable 00078 { 00079 public: 00080 00082 class ScopedBlock 00083 { 00084 public: 00086 ScopedBlock(const std::string &name, Profiler &prof = Profiler::Instance()) : name_(name), prof_(prof) 00087 { 00088 prof_.begin(name); 00089 } 00090 00091 ~ScopedBlock() 00092 { 00093 prof_.end(name_); 00094 } 00095 00096 private: 00097 00098 std::string name_; 00099 Profiler &prof_; 00100 }; 00101 00104 class ScopedStart 00105 { 00106 public: 00107 00109 ScopedStart(Profiler &prof = Profiler::Instance()) : prof_(prof), wasRunning_(prof_.running()) 00110 { 00111 if (!wasRunning_) 00112 prof_.start(); 00113 } 00114 00115 ~ScopedStart() 00116 { 00117 if (!wasRunning_) 00118 prof_.stop(); 00119 } 00120 00121 private: 00122 00123 Profiler &prof_; 00124 bool wasRunning_; 00125 }; 00126 00128 static Profiler& Instance(); 00129 00132 Profiler(bool printOnDestroy = false, bool autoStart = false) : running_(false), printOnDestroy_(printOnDestroy) 00133 { 00134 if (autoStart) 00135 start(); 00136 } 00137 00139 ~Profiler() 00140 { 00141 if (printOnDestroy_ && !data_.empty()) 00142 status(); 00143 } 00144 00146 static void Start() 00147 { 00148 Instance().start(); 00149 } 00150 00152 static void Stop() 00153 { 00154 Instance().stop(); 00155 } 00156 00158 static void Clear() 00159 { 00160 Instance().clear(); 00161 } 00162 00164 void start(); 00165 00167 void stop(); 00168 00170 void clear(); 00171 00173 static void Event(const std::string& name, const unsigned int times = 1) 00174 { 00175 Instance().event(name, times); 00176 } 00177 00179 void event(const std::string &name, const unsigned int times = 1); 00180 00182 static void Average(const std::string& name, const double value) 00183 { 00184 Instance().average(name, value); 00185 } 00186 00188 void average(const std::string &name, const double value); 00189 00191 static void Begin(const std::string &name) 00192 { 00193 Instance().begin(name); 00194 } 00195 00197 static void End(const std::string &name) 00198 { 00199 Instance().end(name); 00200 } 00201 00203 void begin(const std::string &name); 00204 00206 void end(const std::string &name); 00207 00211 static void Status(std::ostream &out = std::cout, bool merge = true) 00212 { 00213 Instance().status(out, merge); 00214 } 00215 00219 void status(std::ostream &out = std::cout, bool merge = true); 00220 00223 static void Console() 00224 { 00225 Instance().console(); 00226 } 00227 00230 void console(); 00231 00233 bool running() const 00234 { 00235 return running_; 00236 } 00237 00239 static bool Running() 00240 { 00241 return Instance().running(); 00242 } 00243 00244 private: 00245 00247 struct TimeInfo 00248 { 00249 TimeInfo() : total(0, 0, 0, 0), shortest(boost::posix_time::pos_infin), longest(boost::posix_time::neg_infin), parts(0) 00250 { 00251 } 00252 00254 time::duration total; 00255 00257 time::duration shortest; 00258 00260 time::duration longest; 00261 00263 unsigned long int parts; 00264 00266 time::point start; 00267 00269 void set() 00270 { 00271 start = time::now(); 00272 } 00273 00275 void update() 00276 { 00277 const time::duration &dt = time::now() - start; 00278 if (dt > longest) 00279 longest = dt; 00280 if (dt < shortest) 00281 shortest = dt; 00282 total = total + dt; 00283 ++parts; 00284 } 00285 }; 00286 00288 struct AvgInfo 00289 { 00291 double total; 00292 00294 double totalSqr; 00295 00297 unsigned long int parts; 00298 }; 00299 00301 struct PerThread 00302 { 00304 std::map<std::string, unsigned long int> events; 00305 00307 std::map<std::string, AvgInfo> avg; 00308 00310 std::map<std::string, TimeInfo> time; 00311 }; 00312 00313 void printThreadInfo(std::ostream &out, const PerThread &data); 00314 00315 boost::mutex lock_; 00316 std::map<boost::thread::id, PerThread> data_; 00317 TimeInfo tinfo_; 00318 bool running_; 00319 bool printOnDestroy_; 00320 00321 }; 00322 } 00323 } 00324 00325 #else 00326 00327 #include <string> 00328 #include <iostream> 00329 00330 /* If profiling is disabled, provide empty implementations for the 00331 public functions */ 00332 namespace ompl 00333 { 00334 00335 namespace tools 00336 { 00337 00338 class Profiler 00339 { 00340 public: 00341 00342 class ScopedBlock 00343 { 00344 public: 00345 00346 ScopedBlock(const std::string &, Profiler & = Profiler::Instance()) 00347 { 00348 } 00349 00350 ~ScopedBlock() 00351 { 00352 } 00353 }; 00354 00355 class ScopedStart 00356 { 00357 public: 00358 00359 ScopedStart(Profiler & = Profiler::Instance()) 00360 { 00361 } 00362 00363 ~ScopedStart() 00364 { 00365 } 00366 }; 00367 00368 static Profiler& Instance(); 00369 00370 Profiler(bool = true, bool = true) 00371 { 00372 } 00373 00374 ~Profiler() 00375 { 00376 } 00377 00378 static void Start() 00379 { 00380 } 00381 00382 static void Stop() 00383 { 00384 } 00385 00386 static void Clear() 00387 { 00388 } 00389 00390 void start() 00391 { 00392 } 00393 00394 void stop() 00395 { 00396 } 00397 00398 void clear() 00399 { 00400 } 00401 00402 static void Event(const std::string&, const unsigned int = 1) 00403 { 00404 } 00405 00406 void event(const std::string &, const unsigned int = 1) 00407 { 00408 } 00409 00410 static void Average(const std::string&, const double) 00411 { 00412 } 00413 00414 void average(const std::string &, const double) 00415 { 00416 } 00417 00418 static void Begin(const std::string &) 00419 { 00420 } 00421 00422 static void End(const std::string &) 00423 { 00424 } 00425 00426 void begin(const std::string &) 00427 { 00428 } 00429 00430 void end(const std::string &) 00431 { 00432 } 00433 00434 static void Status(std::ostream & = std::cout, bool = true) 00435 { 00436 } 00437 00438 void status(std::ostream & = std::cout, bool = true) 00439 { 00440 } 00441 00442 static void Console() 00443 { 00444 } 00445 00446 void console() 00447 { 00448 } 00449 00450 bool running() const 00451 { 00452 return false; 00453 } 00454 00455 static bool Running() 00456 { 00457 return false; 00458 } 00459 }; 00460 } 00461 } 00462 00463 #endif 00464 00465 #endif