COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/time_measure.h @ 1993:2115143eceea

Last change on this file since 1993:2115143eceea was 1960:a60b681d0825, checked in by Alpar Juttner, 14 years ago
  • Increased max. number of iteration
  • Better tests.
File size: 13.4 KB
RevLine 
[906]1/* -*- C++ -*-
2 *
[1956]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
[1359]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[906]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
[921]19#ifndef LEMON_TIME_MEASURE_H
20#define LEMON_TIME_MEASURE_H
[428]21
[1847]22///\ingroup timecount
[428]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
[921]32namespace lemon {
[428]33
[1847]34  /// \addtogroup timecount
[428]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.
[458]48  ///
[1851]49  /// In most cases, perhaps the \ref Timer or the \ref TimeReport
50  /// class is what you want to use instead.
[458]51  ///
52  ///\author Alpar Juttner
[428]53
54  class TimeStamp
55  {
[1689]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;
[428]67    double real_time;
68 
[1689]69    rtms &getTms() {return ts;}
70    const rtms &getTms() const {return ts;}
71
[1780]72    void _reset()
73    { ts.tms_utime=ts.tms_stime=ts.tms_cutime=ts.tms_cstime=0; real_time=0;}
74
[428]75  public:
76
77    ///Read the current time values of the process
78    void stamp()
79    {
80      timeval tv;
[1689]81      tms _ts;
82      times(&_ts);
[428]83      gettimeofday(&tv, 0);real_time=tv.tv_sec+double(tv.tv_usec)/1e6;
[1689]84      ts=_ts;
[428]85    }
86 
87    /// Constructor initializing with zero
88    TimeStamp()
[1780]89    { _reset(); }
[428]90    ///Constructor initializing with the current time values of the process
91    TimeStamp(void *) { stamp();}
92 
[1780]93    ///Set every time value to zero
94    TimeStamp &reset() {_reset();return *this;}
95
[1005]96    ///\e
[428]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    }
[1005]106    ///\e
[428]107    TimeStamp operator+(const TimeStamp &b) const
108    {
109      TimeStamp t(*this);
110      return t+=b;
111    }
[1005]112    ///\e
[428]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    }
[1005]122    ///\e
[428]123    TimeStamp operator-(const TimeStamp &b) const
124    {
125      TimeStamp t(*this);
126      return t-=b;
127    }
[1689]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    }
[428]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
[1689]171    double userTime() const
[428]172    {
173      return double(ts.tms_utime)/sysconf(_SC_CLK_TCK);
174    }
175    ///Gives back the system time of the process
[1689]176    double systemTime() const
[428]177    {
178      return double(ts.tms_stime)/sysconf(_SC_CLK_TCK);
179    }
180    ///Gives back the user time of the process' children
[1689]181    double cUserTime() const
[428]182    {
183      return double(ts.tms_cutime)/sysconf(_SC_CLK_TCK);
184    }
185    ///Gives back the user time of the process' children
[1689]186    double cSystemTime() const
[428]187    {
188      return double(ts.tms_cstime)/sysconf(_SC_CLK_TCK);
189    }
[1780]190    ///Gives back the real time
[1689]191    double realTime() const {return real_time;}
[428]192  };
193
[1689]194  TimeStamp operator*(double b,const TimeStamp &t)
195  {
196    return t*b;
197  }
198 
[1851]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
[1780]223  ///Class for measuring the cpu time and real time usage of the process
[458]224
[1780]225  ///Class for measuring the cpu time and real time usage of the process.
[458]226  ///It is quite easy-to-use, here is a short example.
227  ///\code
[921]228  ///#include<lemon/time_measure.h>
[696]229  ///#include<iostream>
[814]230  ///
[458]231  ///int main()
232  ///{
233  ///
234  ///  ...
235  ///
[696]236  ///  Timer T;
[458]237  ///  doSomething();
[696]238  ///  std::cout << T << '\n';
[1847]239  ///  T.restart();
[458]240  ///  doSomethingElse();
[696]241  ///  std::cout << T << '\n';
[458]242  ///
243  ///  ...
244  ///
245  ///}
246  ///\endcode
247  ///
[1780]248  ///The \ref Timer can also be \ref stop() "stopped" and
[1806]249  ///\ref start() "started" again, so it is possible to compute collected
[1780]250  ///running times.
251  ///
252  ///\warning Depending on the operation system and its actual configuration
[1847]253  ///the time counters have a certain (10ms on a typical Linux system)
254  ///granularity.
[1780]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  ///
[1851]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.
[1780]261  ///
[458]262  ///\todo This shouldn't be Unix (Linux) specific.
[1851]263  ///\sa TimeReport
[458]264  ///
265  ///\author Alpar Juttner
[428]266  class Timer
267  {
[1847]268    int _running; //Timer is running iff _running>0; (_running>=0 always holds)
[1780]269    TimeStamp start_time; //This is the relativ start-time if the timer
[1847]270                          //is _running, the collected _running time otherwise.
[1780]271   
[1847]272    void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
[428]273 
274  public:
[1780]275    ///Constructor.
276
[1953]277    ///\param run indicates whether or not the timer starts immediately.
[1780]278    ///
[1847]279    Timer(bool run=true) :_running(run) {_reset();}
[428]280
[1851]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    ///
[428]289
[1851]290    ///@{
[428]291
[1847]292    ///Reset and stop the time counters
[1069]293
[1847]294    ///This function resets and stops the time counters
295    ///\sa restart()
[1069]296    void reset()
[428]297    {
[1847]298      _running=0;
[428]299      _reset();
300    }
[1005]301
[1780]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    {
[1847]311      if(_running) _running++;
[1780]312      else {
[1850]313        _running=1;
[1780]314        TimeStamp t;
315        t.stamp();
316        start_time=t-start_time;
317      }
318    }
[1847]319
[1780]320   
321    ///Stop the time counters
[1005]322
[1847]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
[1780]332    void stop()
333    {
[1847]334      if(_running && !--_running) {
[1780]335        TimeStamp t;
336        t.stamp();
337        start_time=t-start_time;
338      }
339    }
[1847]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    }
[1780]380   
[1851]381    ///@}
382
383    ///\name Query Functions for the ellapsed time
384
385    ///@{
386
[1005]387    ///Gives back the ellapsed user time of the process
[1689]388    double userTime() const
[1005]389    {
[1689]390      return operator TimeStamp().userTime();
[1005]391    }
392    ///Gives back the ellapsed system time of the process
[1689]393    double systemTime() const
[1005]394    {
[1689]395      return operator TimeStamp().systemTime();
[1005]396    }
397    ///Gives back the ellapsed user time of the process' children
[1689]398    double cUserTime() const
[1005]399    {
[1689]400      return operator TimeStamp().cUserTime();
[1005]401    }
402    ///Gives back the ellapsed user time of the process' children
[1689]403    double cSystemTime() const
[1005]404    {
[1689]405      return operator TimeStamp().cSystemTime();
[1005]406    }
[1780]407    ///Gives back the ellapsed real time
[1689]408    double realTime() const
[1005]409    {
[1689]410      return operator TimeStamp().realTime();
[1005]411    }
[1851]412    ///Computes the ellapsed time
[1005]413
[1851]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    ///@}
[428]430  };
431
[1847]432  ///Same as \ref Timer but prints a report on destruction.
433
434  ///Same as \ref Timer but prints a report on destruction.
[1851]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
[1847]447  class TimeReport : public Timer
448  {
449    std::string _title;
450    std::ostream &_os;
451  public:
452    ///\e
[1851]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)
[1847]459      : Timer(run), _title(title), _os(os){}
[1851]460    ///\e Prints the ellapsed time on destruction.
[1847]461    ~TimeReport()
462    {
[1851]463      _os << _title << *this << std::endl;
[1847]464    }
465  };
466     
[1851]467  ///'Do nothing' version of \ref TimeReport
[428]468
[1851]469  ///\sa TimeReport
[428]470  ///
[1851]471  class NoTimeReport
[428]472  {
[1851]473  public:
474    ///\e
[1855]475    NoTimeReport(std::string,std::ostream &,bool) {}
476    ///\e
477    NoTimeReport(std::string,std::ostream &) {}
478    ///\e
479    NoTimeReport(std::string) {}
[1851]480    ///\e Do nothing.
481    ~NoTimeReport() {}
[428]482
[1851]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     
[1689]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
[1780]501  ///that the full real running time will be roughly between \c min_time
[1689]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.
[1894]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>.
[1689]509  ///\return The average running time of \c f.
510 
511  template<class F>
[1839]512  TimeStamp runningTimeTest(F f,double min_time=10,int *num = NULL,
[1689]513                        TimeStamp *full_time=NULL)
514  {
515    Timer t;
516    TimeStamp full;
517    int total=0;
[1960]518    for(int tn=1;tn < 1<<30; tn*=2) {
[1811]519      for(;total<tn;total++) f();
[1689]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 
[428]530  /// @} 
531
[1689]532
[921]533} //namespace lemon
[428]534
[921]535#endif //LEMON_TIME_MEASURE_H
Note: See TracBrowser for help on using the repository browser.