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