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