All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends

profile.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 FCL_UTIL_PROFILER
00039 #define FCL_UTIL_PROFILER
00040 
00041 #define ENABLE_PROFILING 1
00042 
00043 #ifndef ENABLE_PROFILING
00044 
00046 
00047 #  ifdef NDEBUG
00048 #    define ENABLE_PROFILING 0
00049 #  else
00050 #    define ENABLE_PROFILING 1
00051 #  endif
00052 
00053 #endif
00054 
00055 #if ENABLE_PROFILING
00056 
00057 #include <map>
00058 #include <string>
00059 #include <iostream>
00060 #include <boost/thread.hpp>
00061 #include <boost/noncopyable.hpp>
00062 #include <boost/date_time/posix_time/posix_time.hpp>
00063 
00064 namespace fcl
00065 {
00066 
00068 namespace time
00069 {
00070 
00072 typedef boost::posix_time::ptime         point;
00073 
00075 typedef boost::posix_time::time_duration duration;
00076 
00078 inline point now(void)
00079 {
00080   return boost::posix_time::microsec_clock::universal_time();
00081 }
00082 
00084 inline duration seconds(double sec)
00085 {
00086   long s  = (long)sec;
00087   long us = (long)((sec - s) * 1000000);
00088   return boost::posix_time::seconds(s) + boost::posix_time::microseconds(us);
00089 }
00090 
00092 inline double seconds(const duration &d)
00093 {
00094   return (double)d.total_microseconds() / 1000000.0;
00095 }
00096 
00097 }
00098 
00099 namespace tools
00100 {
00101 
00107 class Profiler : private boost::noncopyable
00108 {
00109 public:
00110 
00112   class ScopedBlock
00113   {
00114   public:
00116     ScopedBlock(const std::string &name, Profiler &prof = Profiler::Instance()) : name_(name), prof_(prof)
00117     {
00118       prof_.begin(name);
00119     }
00120 
00121     ~ScopedBlock(void)
00122     {
00123       prof_.end(name_);
00124     }
00125 
00126   private:
00127 
00128     std::string  name_;
00129     Profiler    &prof_;
00130   };
00131 
00134   class ScopedStart
00135   {
00136   public:
00137 
00139     ScopedStart(Profiler &prof = Profiler::Instance()) : prof_(prof), wasRunning_(prof_.running())
00140     {
00141       if (!wasRunning_)
00142         prof_.start();
00143     }
00144 
00145     ~ScopedStart(void)
00146     {
00147       if (!wasRunning_)
00148         prof_.stop();
00149     }
00150 
00151   private:
00152 
00153     Profiler &prof_;
00154     bool      wasRunning_;
00155   };
00156 
00158   static Profiler& Instance(void);
00159 
00162   Profiler(bool printOnDestroy = false, bool autoStart = false) : running_(false), printOnDestroy_(printOnDestroy)
00163   {
00164     if (autoStart)
00165       start();
00166   }
00167 
00169   ~Profiler(void)
00170   {
00171     if (printOnDestroy_ && !data_.empty())
00172       status();
00173   }
00174 
00176   static void Start(void)
00177   {
00178     Instance().start();
00179   }
00180 
00182   static void Stop(void)
00183   {
00184     Instance().stop();
00185   }
00186 
00188   static void Clear(void)
00189   {
00190     Instance().clear();
00191   }
00192 
00194   void start(void);
00195 
00197   void stop(void);
00198 
00200   void clear(void);
00201 
00203   static void Event(const std::string& name, const unsigned int times = 1)
00204   {
00205     Instance().event(name, times);
00206   }
00207 
00209   void event(const std::string &name, const unsigned int times = 1);
00210 
00212   static void Average(const std::string& name, const double value)
00213   {
00214     Instance().average(name, value);
00215   }
00216 
00218   void average(const std::string &name, const double value);
00219 
00221   static void Begin(const std::string &name)
00222   {
00223     Instance().begin(name);
00224   }
00225 
00227   static void End(const std::string &name)
00228   {
00229     Instance().end(name);
00230   }
00231 
00233   void begin(const std::string &name);
00234 
00236   void end(const std::string &name);
00237 
00241   static void Status(std::ostream &out = std::cout, bool merge = true)
00242   {
00243     Instance().status(out, merge);
00244   }
00245 
00249   void status(std::ostream &out = std::cout, bool merge = true);
00250 
00252   bool running(void) const
00253   {
00254     return running_;
00255   }
00256 
00258   static bool Running(void)
00259   {
00260     return Instance().running();
00261   }
00262 
00263 private:
00264 
00266   struct TimeInfo
00267   {
00268     TimeInfo(void) : total(0, 0, 0, 0), shortest(boost::posix_time::pos_infin), longest(boost::posix_time::neg_infin), parts(0)
00269     {
00270     }
00271 
00273     time::duration    total;
00274 
00276     time::duration    shortest;
00277 
00279     time::duration    longest;
00280 
00282     unsigned long int parts;
00283 
00285     time::point       start;
00286 
00288     void set(void)
00289     {
00290       start = time::now();
00291     }
00292 
00294     void update(void)
00295     {
00296       const time::duration &dt = time::now() - start;
00297       if (dt > longest)
00298         longest = dt;
00299       if (dt < shortest)
00300         shortest = dt;
00301       total = total + dt;
00302       ++parts;
00303     }
00304   };
00305 
00307   struct AvgInfo
00308   {
00310     double            total;
00311 
00313     double            totalSqr;
00314 
00316     unsigned long int parts;
00317   };
00318 
00320   struct PerThread
00321   {
00323     std::map<std::string, unsigned long int> events;
00324 
00326     std::map<std::string, AvgInfo>           avg;
00327 
00329     std::map<std::string, TimeInfo>          time;
00330   };
00331 
00332   void printThreadInfo(std::ostream &out, const PerThread &data);
00333 
00334   boost::mutex                           lock_;
00335   std::map<boost::thread::id, PerThread> data_;
00336   TimeInfo                               tinfo_;
00337   bool                                   running_;
00338   bool                                   printOnDestroy_;
00339 
00340 };
00341 }
00342 }
00343 
00344 #else
00345 
00346 #include <string>
00347 #include <iostream>
00348 
00350 namespace fcl
00351 {
00352 
00353 namespace tools
00354 {
00355 
00356 class Profiler
00357 {
00358 public:
00359 
00360   class ScopedBlock
00361   {
00362   public:
00363 
00364     ScopedBlock(const std::string &, Profiler & = Profiler::Instance())
00365     {
00366     }
00367 
00368     ~ScopedBlock(void)
00369     {
00370     }
00371   };
00372 
00373   class ScopedStart
00374   {
00375   public:
00376 
00377     ScopedStart(Profiler & = Profiler::Instance())
00378     {
00379     }
00380 
00381     ~ScopedStart(void)
00382     {
00383     }
00384   };
00385 
00386   static Profiler& Instance(void);
00387 
00388   Profiler(bool = true, bool = true)
00389   {
00390   }
00391 
00392   ~Profiler(void)
00393   {
00394   }
00395 
00396   static void Start(void)
00397   {
00398   }
00399 
00400   static void Stop(void)
00401   {
00402   }
00403 
00404   static void Clear(void)
00405   {
00406   }
00407 
00408   void start(void)
00409   {
00410   }
00411 
00412   void stop(void)
00413   {
00414   }
00415 
00416   void clear(void)
00417   {
00418   }
00419 
00420   static void Event(const std::string&, const unsigned int = 1)
00421   {
00422   }
00423 
00424   void event(const std::string &, const unsigned int = 1)
00425   {
00426   }
00427 
00428   static void Average(const std::string&, const double)
00429   {
00430   }
00431 
00432   void average(const std::string &, const double)
00433   {
00434   }
00435 
00436   static void Begin(const std::string &)
00437   {
00438   }
00439 
00440   static void End(const std::string &)
00441   {
00442   }
00443 
00444   void begin(const std::string &)
00445   {
00446   }
00447 
00448   void end(const std::string &)
00449   {
00450   }
00451 
00452   static void Status(std::ostream & = std::cout, bool = true)
00453   {
00454   }
00455 
00456   void status(std::ostream & = std::cout, bool = true)
00457   {
00458   }
00459 
00460   bool running(void) const
00461   {
00462     return false;
00463   }
00464 
00465   static bool Running(void)
00466   {
00467     return false;
00468   }
00469 };
00470 }
00471 }
00472 
00473 #endif
00474 
00475 #endif