COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/time_measure.h @ 497:47b376a5a2a7

Last change on this file since 497:47b376a5a2a7 was 494:097d7c4634ea, checked in by Alpar Juttner <alpar@…>, 16 years ago

Fix missing 'inline' specifier in time_measure.h (#239)

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