lemon/time_measure.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1956 a055123339d5
child 2027 119db4e6ab2c
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
     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