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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines