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