lemon/time_measure.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1806 1530c115580f
child 1839 b2dfd32b4895
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
     1 /* -*- C++ -*-
     2  * lemon/time_measure.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 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 misc
    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 misc
    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 \ref Timer class is what you want to use instead.
    48   ///
    49   ///\author Alpar Juttner
    50 
    51   class TimeStamp
    52   {
    53     struct rtms 
    54     {
    55       double tms_utime;
    56       double tms_stime;
    57       double tms_cutime;
    58       double tms_cstime;
    59       rtms() {}
    60       rtms(tms ts) : tms_utime(ts.tms_utime), tms_stime(ts.tms_stime),
    61 		     tms_cutime(ts.tms_cutime), tms_cstime(ts.tms_cstime) {}
    62     };
    63     rtms ts;
    64     double real_time;
    65   
    66     rtms &getTms() {return ts;}
    67     const rtms &getTms() const {return ts;}
    68 
    69     void _reset() 
    70     { ts.tms_utime=ts.tms_stime=ts.tms_cutime=ts.tms_cstime=0; real_time=0;}
    71 
    72   public:
    73 
    74     ///Read the current time values of the process
    75     void stamp()
    76     {
    77       timeval tv;
    78       tms _ts;
    79       times(&_ts);
    80       gettimeofday(&tv, 0);real_time=tv.tv_sec+double(tv.tv_usec)/1e6;
    81       ts=_ts;
    82     }
    83   
    84     /// Constructor initializing with zero
    85     TimeStamp()
    86     { _reset(); }
    87     ///Constructor initializing with the current time values of the process
    88     TimeStamp(void *) { stamp();}
    89   
    90     ///Set every time value to zero
    91     TimeStamp &reset() {_reset();return *this;}
    92 
    93     ///\e
    94     TimeStamp &operator+=(const TimeStamp &b)
    95     {
    96       ts.tms_utime+=b.ts.tms_utime;
    97       ts.tms_stime+=b.ts.tms_stime;
    98       ts.tms_cutime+=b.ts.tms_cutime;
    99       ts.tms_cstime+=b.ts.tms_cstime;
   100       real_time+=b.real_time;
   101       return *this;
   102     }
   103     ///\e
   104     TimeStamp operator+(const TimeStamp &b) const
   105     {
   106       TimeStamp t(*this);
   107       return t+=b;
   108     }
   109     ///\e
   110     TimeStamp &operator-=(const TimeStamp &b)
   111     {
   112       ts.tms_utime-=b.ts.tms_utime;
   113       ts.tms_stime-=b.ts.tms_stime;
   114       ts.tms_cutime-=b.ts.tms_cutime;
   115       ts.tms_cstime-=b.ts.tms_cstime;
   116       real_time-=b.real_time;
   117       return *this;
   118     }
   119     ///\e
   120     TimeStamp operator-(const TimeStamp &b) const
   121     {
   122       TimeStamp t(*this);
   123       return t-=b;
   124     }
   125     ///\e
   126     TimeStamp &operator*=(double b)
   127     {
   128       ts.tms_utime*=b;
   129       ts.tms_stime*=b;
   130       ts.tms_cutime*=b;
   131       ts.tms_cstime*=b;
   132       real_time*=b;
   133       return *this;
   134     }
   135     ///\e
   136     TimeStamp operator*(double b) const
   137     {
   138       TimeStamp t(*this);
   139       return t*=b;
   140     }
   141     friend TimeStamp operator*(double b,const TimeStamp &t);
   142     ///\e
   143     TimeStamp &operator/=(double b)
   144     {
   145       ts.tms_utime/=b;
   146       ts.tms_stime/=b;
   147       ts.tms_cutime/=b;
   148       ts.tms_cstime/=b;
   149       real_time/=b;
   150       return *this;
   151     }
   152     ///\e
   153     TimeStamp operator/(double b) const
   154     {
   155       TimeStamp t(*this);
   156       return t/=b;
   157     }
   158     ///The time ellapsed since the last call of stamp()
   159     TimeStamp ellapsed() const
   160     {
   161       TimeStamp t(NULL);
   162       return t-*this;
   163     }
   164   
   165     friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t);
   166   
   167     ///Gives back the user time of the process
   168     double userTime() const
   169     {
   170       return double(ts.tms_utime)/sysconf(_SC_CLK_TCK);
   171     }
   172     ///Gives back the system time of the process
   173     double systemTime() const
   174     {
   175       return double(ts.tms_stime)/sysconf(_SC_CLK_TCK);
   176     }
   177     ///Gives back the user time of the process' children
   178     double cUserTime() const
   179     {
   180       return double(ts.tms_cutime)/sysconf(_SC_CLK_TCK);
   181     }
   182     ///Gives back the user time of the process' children
   183     double cSystemTime() const
   184     {
   185       return double(ts.tms_cstime)/sysconf(_SC_CLK_TCK);
   186     }
   187     ///Gives back the real time
   188     double realTime() const {return real_time;}
   189   };
   190 
   191   TimeStamp operator*(double b,const TimeStamp &t) 
   192   {
   193     return t*b;
   194   }
   195   
   196   ///Class for measuring the cpu time and real time usage of the process
   197 
   198   ///Class for measuring the cpu time and real time usage of the process.
   199   ///It is quite easy-to-use, here is a short example.
   200   ///\code
   201   ///#include<lemon/time_measure.h>
   202   ///#include<iostream>
   203   ///
   204   ///int main()
   205   ///{
   206   ///
   207   ///  ...
   208   ///
   209   ///  Timer T;
   210   ///  doSomething();
   211   ///  std::cout << T << '\n';
   212   ///  T.reset();
   213   ///  doSomethingElse();
   214   ///  std::cout << T << '\n';
   215   ///
   216   ///  ...
   217   ///
   218   ///}
   219   ///\endcode
   220   ///
   221   ///The \ref Timer can also be \ref stop() "stopped" and
   222   ///\ref start() "started" again, so it is possible to compute collected
   223   ///running times.
   224   ///
   225   ///\warning Depending on the operation system and its actual configuration
   226   ///the time counters have a certain (relatively big) granularity.
   227   ///Therefore this tool is not appropriate to measure very short times.
   228   ///Also, if you start and stop the timer very frequently, it could lead
   229   ///distorted results.
   230   ///
   231   ///The \ref Timer also counts the number of \ref start()
   232   ///executions, and is stops only after the same amount (or more)
   233   ///\ref stop() "stop()"s. This can be useful e.g. to compute the running time
   234   ///of recursive functions.
   235   ///
   236   ///\todo This shouldn't be Unix (Linux) specific.
   237   ///
   238   ///\author Alpar Juttner
   239   class Timer
   240   {
   241     int running; //Timer is running iff running>0; (running>=0 always holds)
   242     TimeStamp start_time; //This is the relativ start-time if the timer
   243                           //is running, the collected running time otherwise.
   244     
   245     void _reset() {if(running) start_time.stamp(); else start_time.reset();}
   246   
   247   public: 
   248     ///Constructor.
   249 
   250     ///\param _running indicates whether or not the timer starts immediately.
   251     ///
   252     Timer(bool _running=true) :running(_running) {_reset();}
   253 
   254     ///Computes the ellapsed time
   255 
   256     ///This conversion computes the ellapsed time
   257     ///
   258     operator TimeStamp () const
   259     {
   260       TimeStamp t;
   261       t.stamp();
   262       return running?t-start_time:start_time;
   263     }
   264 
   265     ///Resets the time counters
   266 
   267     ///Resets the time counters
   268     ///
   269     void reset()
   270     {
   271       _reset();
   272     }
   273 
   274     ///Start the time counters
   275     
   276     ///This function starts the time counters.
   277     ///
   278     ///If the timer is started more than ones, it will remain running
   279     ///until the same amount of \ref stop() is called.
   280     ///\sa stop()
   281     void start() 
   282     {
   283       if(running) running++;
   284       else {
   285 	TimeStamp t;
   286 	t.stamp();
   287 	start_time=t-start_time;
   288       }
   289     }
   290     
   291     ///Stop the time counters
   292 
   293     ///This function stops the time counters.
   294     ///
   295     ///\sa stop()
   296     void stop() 
   297     {
   298       if(running && !--running) {
   299 	TimeStamp t;
   300 	t.stamp();
   301 	start_time=t-start_time;
   302       }
   303     }
   304     
   305     ///Gives back the ellapsed user time of the process
   306     double userTime() const
   307     {
   308       return operator TimeStamp().userTime();
   309     }
   310     ///Gives back the ellapsed system time of the process
   311     double systemTime() const
   312     {
   313       return operator TimeStamp().systemTime();
   314     }
   315     ///Gives back the ellapsed user time of the process' children
   316     double cUserTime() const
   317     {
   318       return operator TimeStamp().cUserTime();
   319     }
   320     ///Gives back the ellapsed user time of the process' children
   321     double cSystemTime() const
   322     {
   323       return operator TimeStamp().cSystemTime();
   324     }
   325     ///Gives back the ellapsed real time
   326     double realTime() const
   327     {
   328       return operator TimeStamp().realTime();
   329     }
   330 
   331   };
   332 
   333   ///Prints the time counters
   334 
   335   ///Prints the time counters in the following form:
   336   ///
   337   /// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt>
   338   ///
   339   /// where the values are the
   340   /// \li \c u: user cpu time,
   341   /// \li \c s: system cpu time,
   342   /// \li \c cu: user cpu time of children,
   343   /// \li \c cs: system cpu time of children,
   344   /// \li \c real: real time.
   345   /// \relates TimeStamp
   346   inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
   347   {
   348     long cls = sysconf(_SC_CLK_TCK);
   349     os << "u: " << double(t.getTms().tms_utime)/cls <<
   350       "s, s: " << double(t.getTms().tms_stime)/cls <<
   351       "s, cu: " << double(t.getTms().tms_cutime)/cls <<
   352       "s, cs: " << double(t.getTms().tms_cstime)/cls <<
   353       "s, real: " << t.realTime() << "s";
   354     return os;
   355   }
   356 
   357   
   358   ///Tool to measure the running time more exactly.
   359   
   360   ///This function calls \c f several times and returns the average
   361   ///running time. The number of the executions will be choosen in such a way
   362   ///that the full real running time will be roughly between \c min_time
   363   ///and <tt>2*min_time</tt>.
   364   ///\param f the function object to be measured.
   365   ///\param min_time the minimum total running time.
   366   ///\retval num if it is not \c NULL, then *num will contain the actual
   367   ///        number of execution of \c f.
   368   ///\retval full_time if it is not \c NULL, then *full_time
   369   ///        will contain the actual
   370   ///        total running time.
   371   ///\return The average running time of \c f.
   372   
   373   template<class F>
   374   TimeStamp runningTimeTest(const F &f,double min_time=10,int *num = NULL,
   375 			TimeStamp *full_time=NULL)
   376   {
   377     Timer t;
   378     TimeStamp full;
   379     int total=0;
   380     for(int tn=1;tn < 1<<24; tn*=2) {
   381       for(;total<tn;total++) f();
   382       full=t;
   383       if(full.realTime()>min_time) {
   384 	if(num) *num=total;
   385 	if(full_time) *full_time=full;
   386       return full/total;
   387       }
   388     }
   389     return TimeStamp();
   390   }
   391   
   392   /// @}  
   393 
   394 
   395 } //namespace lemon
   396 
   397 #endif //LEMON_TIME_MEASURE_H