COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/time_measure.h @ 2000:ebcc93ead7da

Last change on this file since 2000:ebcc93ead7da was 1960:a60b681d0825, checked in by Alpar Juttner, 18 years ago
  • Increased max. number of iteration
  • Better tests.
File size: 13.4 KB
Line 
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
32namespace 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
Note: See TracBrowser for help on using the repository browser.