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