lemon/time_measure.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 584 33c6b6e755cd
child 1054 c40a9d94442d
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

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