lemon/time_measure.h
author alpar
Thu, 02 Feb 2006 08:52:20 +0000
changeset 1941 9fe177e0437d
parent 1875 98698b69a902
child 1953 d4f411003580
permissions -rw-r--r--
The version tag of the trunk is svn-head
     1 /* -*- C++ -*-
     2  * lemon/time_measure.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_TIME_MEASURE_H
    18 #define LEMON_TIME_MEASURE_H
    19 
    20 ///\ingroup timecount
    21 ///\file
    22 ///\brief Tools for measuring cpu usage
    23 
    24 #include <sys/time.h>
    25 #include <sys/times.h>
    26 #include <fstream>
    27 #include <iostream>
    28 #include <unistd.h>
    29 
    30 namespace lemon {
    31 
    32   /// \addtogroup timecount
    33   /// @{
    34 
    35   /// A class to store (cpu)time instances.
    36 
    37   /// This class stores five time values.
    38   /// - a real time
    39   /// - a user cpu time
    40   /// - a system cpu time
    41   /// - a user cpu time of children
    42   /// - a system cpu time of children
    43   ///
    44   /// TimeStamp's can be added to or substracted from each other and
    45   /// they can be pushed to a stream.
    46   ///
    47   /// In most cases, perhaps the \ref Timer or the \ref TimeReport
    48   /// class is what you want to use instead.
    49   ///
    50   ///\author Alpar Juttner
    51 
    52   class TimeStamp
    53   {
    54     struct rtms 
    55     {
    56       double tms_utime;
    57       double tms_stime;
    58       double tms_cutime;
    59       double tms_cstime;
    60       rtms() {}
    61       rtms(tms ts) : tms_utime(ts.tms_utime), tms_stime(ts.tms_stime),
    62 		     tms_cutime(ts.tms_cutime), tms_cstime(ts.tms_cstime) {}
    63     };
    64     rtms ts;
    65     double real_time;
    66   
    67     rtms &getTms() {return ts;}
    68     const rtms &getTms() const {return ts;}
    69 
    70     void _reset() 
    71     { ts.tms_utime=ts.tms_stime=ts.tms_cutime=ts.tms_cstime=0; real_time=0;}
    72 
    73   public:
    74 
    75     ///Read the current time values of the process
    76     void stamp()
    77     {
    78       timeval tv;
    79       tms _ts;
    80       times(&_ts);
    81       gettimeofday(&tv, 0);real_time=tv.tv_sec+double(tv.tv_usec)/1e6;
    82       ts=_ts;
    83     }
    84   
    85     /// Constructor initializing with zero
    86     TimeStamp()
    87     { _reset(); }
    88     ///Constructor initializing with the current time values of the process
    89     TimeStamp(void *) { stamp();}
    90   
    91     ///Set every time value to zero
    92     TimeStamp &reset() {_reset();return *this;}
    93 
    94     ///\e
    95     TimeStamp &operator+=(const TimeStamp &b)
    96     {
    97       ts.tms_utime+=b.ts.tms_utime;
    98       ts.tms_stime+=b.ts.tms_stime;
    99       ts.tms_cutime+=b.ts.tms_cutime;
   100       ts.tms_cstime+=b.ts.tms_cstime;
   101       real_time+=b.real_time;
   102       return *this;
   103     }
   104     ///\e
   105     TimeStamp operator+(const TimeStamp &b) const
   106     {
   107       TimeStamp t(*this);
   108       return t+=b;
   109     }
   110     ///\e
   111     TimeStamp &operator-=(const TimeStamp &b)
   112     {
   113       ts.tms_utime-=b.ts.tms_utime;
   114       ts.tms_stime-=b.ts.tms_stime;
   115       ts.tms_cutime-=b.ts.tms_cutime;
   116       ts.tms_cstime-=b.ts.tms_cstime;
   117       real_time-=b.real_time;
   118       return *this;
   119     }
   120     ///\e
   121     TimeStamp operator-(const TimeStamp &b) const
   122     {
   123       TimeStamp t(*this);
   124       return t-=b;
   125     }
   126     ///\e
   127     TimeStamp &operator*=(double b)
   128     {
   129       ts.tms_utime*=b;
   130       ts.tms_stime*=b;
   131       ts.tms_cutime*=b;
   132       ts.tms_cstime*=b;
   133       real_time*=b;
   134       return *this;
   135     }
   136     ///\e
   137     TimeStamp operator*(double b) const
   138     {
   139       TimeStamp t(*this);
   140       return t*=b;
   141     }
   142     friend TimeStamp operator*(double b,const TimeStamp &t);
   143     ///\e
   144     TimeStamp &operator/=(double b)
   145     {
   146       ts.tms_utime/=b;
   147       ts.tms_stime/=b;
   148       ts.tms_cutime/=b;
   149       ts.tms_cstime/=b;
   150       real_time/=b;
   151       return *this;
   152     }
   153     ///\e
   154     TimeStamp operator/(double b) const
   155     {
   156       TimeStamp t(*this);
   157       return t/=b;
   158     }
   159     ///The time ellapsed since the last call of stamp()
   160     TimeStamp ellapsed() const
   161     {
   162       TimeStamp t(NULL);
   163       return t-*this;
   164     }
   165   
   166     friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t);
   167   
   168     ///Gives back the user time of the process
   169     double userTime() const
   170     {
   171       return double(ts.tms_utime)/sysconf(_SC_CLK_TCK);
   172     }
   173     ///Gives back the system time of the process
   174     double systemTime() const
   175     {
   176       return double(ts.tms_stime)/sysconf(_SC_CLK_TCK);
   177     }
   178     ///Gives back the user time of the process' children
   179     double cUserTime() const
   180     {
   181       return double(ts.tms_cutime)/sysconf(_SC_CLK_TCK);
   182     }
   183     ///Gives back the user time of the process' children
   184     double cSystemTime() const
   185     {
   186       return double(ts.tms_cstime)/sysconf(_SC_CLK_TCK);
   187     }
   188     ///Gives back the real time
   189     double realTime() const {return real_time;}
   190   };
   191 
   192   TimeStamp operator*(double b,const TimeStamp &t) 
   193   {
   194     return t*b;
   195   }
   196   
   197   ///Prints the time counters
   198 
   199   ///Prints the time counters in the following form:
   200   ///
   201   /// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt>
   202   ///
   203   /// where the values are the
   204   /// \li \c u: user cpu time,
   205   /// \li \c s: system cpu time,
   206   /// \li \c cu: user cpu time of children,
   207   /// \li \c cs: system cpu time of children,
   208   /// \li \c real: real time.
   209   /// \relates TimeStamp
   210   inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
   211   {
   212     long cls = sysconf(_SC_CLK_TCK);
   213     os << "u: " << double(t.getTms().tms_utime)/cls <<
   214       "s, s: " << double(t.getTms().tms_stime)/cls <<
   215       "s, cu: " << double(t.getTms().tms_cutime)/cls <<
   216       "s, cs: " << double(t.getTms().tms_cstime)/cls <<
   217       "s, real: " << t.realTime() << "s";
   218     return os;
   219   }
   220 
   221   ///Class for measuring the cpu time and real time usage of the process
   222 
   223   ///Class for measuring the cpu time and real time usage of the process.
   224   ///It is quite easy-to-use, here is a short example.
   225   ///\code
   226   ///#include<lemon/time_measure.h>
   227   ///#include<iostream>
   228   ///
   229   ///int main()
   230   ///{
   231   ///
   232   ///  ...
   233   ///
   234   ///  Timer T;
   235   ///  doSomething();
   236   ///  std::cout << T << '\n';
   237   ///  T.restart();
   238   ///  doSomethingElse();
   239   ///  std::cout << T << '\n';
   240   ///
   241   ///  ...
   242   ///
   243   ///}
   244   ///\endcode
   245   ///
   246   ///The \ref Timer can also be \ref stop() "stopped" and
   247   ///\ref start() "started" again, so it is possible to compute collected
   248   ///running times.
   249   ///
   250   ///\warning Depending on the operation system and its actual configuration
   251   ///the time counters have a certain (10ms on a typical Linux system)
   252   ///granularity.
   253   ///Therefore this tool is not appropriate to measure very short times.
   254   ///Also, if you start and stop the timer very frequently, it could lead
   255   ///distorted results.
   256   ///
   257   ///\note If you want to measure the running time of the execution of a certain
   258   ///function, consider the usage of \ref TimeReport instead.
   259   ///
   260   ///\todo This shouldn't be Unix (Linux) specific.
   261   ///\sa TimeReport
   262   ///
   263   ///\author Alpar Juttner
   264   class Timer
   265   {
   266     int _running; //Timer is running iff _running>0; (_running>=0 always holds)
   267     TimeStamp start_time; //This is the relativ start-time if the timer
   268                           //is _running, the collected _running time otherwise.
   269     
   270     void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
   271   
   272   public: 
   273     ///Constructor.
   274 
   275     ///\param _running indicates whether or not the timer starts immediately.
   276     ///
   277     Timer(bool run=true) :_running(run) {_reset();}
   278 
   279     ///\name Control the state of the timer
   280     ///Basically a Timer can be either running or stopped,
   281     ///but it provides a bit finer control on the execution.
   282     ///The \ref Timer also counts the number of \ref start()
   283     ///executions, and is stops only after the same amount (or more)
   284     ///\ref stop() "stop()"s. This can be useful e.g. to compute the running time
   285     ///of recursive functions.
   286     ///
   287 
   288     ///@{
   289 
   290     ///Reset and stop the time counters
   291 
   292     ///This function resets and stops the time counters
   293     ///\sa restart()
   294     void reset()
   295     {
   296       _running=0;
   297       _reset();
   298     }
   299 
   300     ///Start the time counters
   301     
   302     ///This function starts the time counters.
   303     ///
   304     ///If the timer is started more than ones, it will remain running
   305     ///until the same amount of \ref stop() is called.
   306     ///\sa stop()
   307     void start() 
   308     {
   309       if(_running) _running++;
   310       else {
   311 	_running=1;
   312 	TimeStamp t;
   313 	t.stamp();
   314 	start_time=t-start_time;
   315       }
   316     }
   317 
   318     
   319     ///Stop the time counters
   320 
   321     ///This function stops the time counters. If start() was executed more than
   322     ///once, then the same number of stop() execution is necessary the really
   323     ///stop the timer.
   324     /// 
   325     ///\sa halt()
   326     ///\sa start()
   327     ///\sa restart()
   328     ///\sa reset()
   329 
   330     void stop() 
   331     {
   332       if(_running && !--_running) {
   333 	TimeStamp t;
   334 	t.stamp();
   335 	start_time=t-start_time;
   336       }
   337     }
   338 
   339     ///Halt (i.e stop immediately) the time counters
   340 
   341     ///This function stops immediately the time counters.
   342     ///
   343     ///\sa stop()
   344     ///\sa restart()
   345     ///\sa reset()
   346 
   347     void halt() 
   348     {
   349       if(_running) {
   350 	_running=0;
   351 	TimeStamp t;
   352 	t.stamp();
   353 	start_time=t-start_time;
   354       }
   355     }
   356 
   357     ///Returns the running state of the timer
   358 
   359     ///This function returns the number of stop() exections that is
   360     ///necessary to really stop the timer.
   361     ///For example the timer
   362     ///is running if and only if the return value is \c true
   363     ///(i.e. greater than
   364     ///zero).
   365     int running()  { return _running; }
   366     
   367     
   368     ///Restart the time counters
   369 
   370     ///This function is a shorthand for
   371     ///a reset() and a start() calls.
   372     ///
   373     void restart() 
   374     {
   375       reset();
   376       start();
   377     }
   378     
   379     ///@}
   380 
   381     ///\name Query Functions for the ellapsed time
   382 
   383     ///@{
   384 
   385     ///Gives back the ellapsed user time of the process
   386     double userTime() const
   387     {
   388       return operator TimeStamp().userTime();
   389     }
   390     ///Gives back the ellapsed system time of the process
   391     double systemTime() const
   392     {
   393       return operator TimeStamp().systemTime();
   394     }
   395     ///Gives back the ellapsed user time of the process' children
   396     double cUserTime() const
   397     {
   398       return operator TimeStamp().cUserTime();
   399     }
   400     ///Gives back the ellapsed user time of the process' children
   401     double cSystemTime() const
   402     {
   403       return operator TimeStamp().cSystemTime();
   404     }
   405     ///Gives back the ellapsed real time
   406     double realTime() const
   407     {
   408       return operator TimeStamp().realTime();
   409     }
   410     ///Computes the ellapsed time
   411 
   412     ///This conversion computes the ellapsed time, therefore you can print
   413     ///the ellapsed time like this.
   414     ///\code
   415     ///  Timer T;
   416     ///  doSomething();
   417     ///  std::cout << T << '\n';
   418     ///\endcode
   419     operator TimeStamp () const
   420     {
   421       TimeStamp t;
   422       t.stamp();
   423       return _running?t-start_time:start_time;
   424     }
   425 
   426 
   427     ///@}
   428   };
   429 
   430   ///Same as \ref Timer but prints a report on destruction.
   431 
   432   ///Same as \ref Timer but prints a report on destruction.
   433   ///This example shows its usage.
   434   ///\code
   435   ///  void myAlg(ListGraph &g,int n)
   436   ///  {
   437   ///    TimeReport TR("Running time of myAlg: ");
   438   ///    ... //Here comes the algorithm
   439   ///  }
   440   ///\endcode
   441   ///
   442   ///\sa Timer
   443   ///\sa NoTimeReport
   444   ///\todo There is no test case for this
   445   class TimeReport : public Timer 
   446   {
   447     std::string _title;
   448     std::ostream &_os;
   449   public:
   450     ///\e
   451 
   452     ///\param title This text will be printed before the ellapsed time.
   453     ///\param os The stream to print the report to.
   454     ///\param run Sets whether the timer should start immediately.
   455 
   456     TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true) 
   457       : Timer(run), _title(title), _os(os){}
   458     ///\e Prints the ellapsed time on destruction.
   459     ~TimeReport() 
   460     {
   461       _os << _title << *this << std::endl;
   462     }
   463   };
   464       
   465   ///'Do nothing' version of \ref TimeReport
   466 
   467   ///\sa TimeReport
   468   ///
   469   class NoTimeReport
   470   {
   471   public:
   472     ///\e
   473     NoTimeReport(std::string,std::ostream &,bool) {}
   474     ///\e
   475     NoTimeReport(std::string,std::ostream &) {}
   476     ///\e
   477     NoTimeReport(std::string) {}
   478     ///\e Do nothing.
   479     ~NoTimeReport() {}
   480 
   481     operator TimeStamp () const { return TimeStamp(); }
   482     void reset() {}
   483     void start() {}
   484     void stop() {}
   485     void halt() {} 
   486     int running() { return 0; }
   487     void restart() {}
   488     double userTime() const { return 0; }
   489     double systemTime() const { return 0; }
   490     double cUserTime() const { return 0; }
   491     double cSystemTime() const { return 0; }
   492     double realTime() const { return 0; }
   493   };
   494       
   495   ///Tool to measure the running time more exactly.
   496   
   497   ///This function calls \c f several times and returns the average
   498   ///running time. The number of the executions will be choosen in such a way
   499   ///that the full real running time will be roughly between \c min_time
   500   ///and <tt>2*min_time</tt>.
   501   ///\param f the function object to be measured.
   502   ///\param min_time the minimum total running time.
   503   ///\retval num if it is not \c NULL, then the actual
   504   ///        number of execution of \c f will be written into <tt>*num</tt>.
   505   ///\retval full_time if it is not \c NULL, then the actual
   506   ///        total running time will be written into <tt>*full_time</tt>.
   507   ///\return The average running time of \c f.
   508   
   509   template<class F>
   510   TimeStamp runningTimeTest(F f,double min_time=10,int *num = NULL,
   511 			TimeStamp *full_time=NULL)
   512   {
   513     Timer t;
   514     TimeStamp full;
   515     int total=0;
   516     for(int tn=1;tn < 1<<24; tn*=2) {
   517       for(;total<tn;total++) f();
   518       full=t;
   519       if(full.realTime()>min_time) {
   520 	if(num) *num=total;
   521 	if(full_time) *full_time=full;
   522       return full/total;
   523       }
   524     }
   525     return TimeStamp();
   526   }
   527   
   528   /// @}  
   529 
   530 
   531 } //namespace lemon
   532 
   533 #endif //LEMON_TIME_MEASURE_H