3

I'm trying to benchmark a piece of code. It is based on this code here with the interesting part basically looking like this:

    auto t0 = std::chrono::high_resolution_clock::now();
    ...
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << secs(t1-t0).count() << " s\n";

The problem is that I am on a shared machine, and this is giving me wall time, so my results are not giving me anything consistent. What I really need is some sort of stopwatch tool that will allow me get just the time in which my code is running, rather than the wall time. What options are there? I'm on a Linux machine if it comes to system specific calls, but I'd rather keep this code portable if possible.

I've looked at other questions such as this and this but they all seem to offer wall time solutions.

Community
  • 1
  • 1
GBleaney
  • 2,096
  • 2
  • 22
  • 40
  • 3
    Have you considered isolating the code in `main`, compiling, and running it via [`time`](http://en.wikipedia.org/wiki/Time_(Unix))? (Not the best for measuring small pieces of code, but since you're using seconds, I assume this should be good enough) – user123 Jul 03 '14 at 18:35
  • I could do that as a last resort, however I'm running a ton of tests with a ton of configuration, and if I have to keep copying into main, this testing will take a lot longer and will be a lot less pleasant – GBleaney Jul 03 '14 at 18:39
  • When you say "time", do you mean CPU time? If you were to exclude all other process's use of the CPU, would you want the time to include i/o? – wallyk Jul 03 '14 at 18:40
  • There is no I/O time in this particular case. Its just small snippets of code that are testing the behavior of an unordered map with different algorithms and different input. – GBleaney Jul 03 '14 at 19:00
  • I was expecting to see some mention of gprof and gcc flags to make it work. Why not use a profiler for this? See questions like http://stackoverflow.com/questions/21072058/gprof-specific-function-time. – wojciii Jul 03 '14 at 21:55

4 Answers4

4

If available on your OS you can use the times API to get similar results as the built in time command.

#include <sys/times.h>
...
struct tms  start, end;
times(&start);
//Do command
times(&end);
clock_t usr_time = end->tms_utime - start->tms_utime;
clock_t sys_time = end->tms_stime - start->tms_stime;

To be 100% complete you should check that the result of times is not equal to -1 and check the errno code otherwise.

KillianDS
  • 16,936
  • 4
  • 61
  • 70
  • 1
    There is a typo in the answer. `start` and `end` are not pointers so the calculations should be `clock_t usr_time = end.tms_utime - start.tms_utime;` and `clock_t sys_time = end.tms_stime - start.tms_stime;` – joesdiner Apr 01 '20 at 13:23
  • Also, the units returned by `times()` is the number of elapsed ticks as per `CLOCKS_PER_SEC`. So to get the number of seconds of elapsed time do `(double) usr_time / CLOCKS_PER_SEC` (I think). – joesdiner Apr 01 '20 at 14:54
  • Kilian please take the time to correct the above typo. – Alex M.M. Apr 19 '20 at 17:21
2

For Linux

  #include <time.h>
  #include <stdio.h>

  double  theseSecs = 0.0;
  double  startSecs = 0.0;
  double  secs;
  double  CPUsecs = 0.0;
  double  CPUutilisation = 0.0;
  double  answer = 0;
  clock_t starts;

  void start_CPU_time()
  {      
      starts = clock();;
      return;
  }

  void end_CPU_time()
  {
      CPUsecs = (double)(clock() - starts)/(double)CLOCKS_PER_SEC;
      return;
  }    

  struct timespec tp1;
  void getSecs()
  {
     clock_gettime(CLOCK_REALTIME, &tp1);
     theseSecs =  tp1.tv_sec + tp1.tv_nsec / 1e9;           
     return;
  }

  void start_time()
  {
      getSecs();
      startSecs = theseSecs;
      return;
  }

  void end_time()
  {
      getSecs();
      secs    = theseSecs - startSecs;
      return;
  }    

  void calculate()
  {
      int i, j;
      for (i=1; i<100001; i++)
      {
          for (j=1; j<10001; j++)
          {
              answer = answer + (float)i / 100000000.0;
          }
      }
  }

 void main()
 {
     start_time();
     start_CPU_time();
     calculate();
     end_time();
     end_CPU_time();
     CPUutilisation = CPUsecs /  secs * 100.0;
     printf("\n Answer %10.1f, Elapsed Time %7.4f, CPU Time %7.4f, CPU Ut %3.0f%\n",
              answer, secs, CPUsecs, CPUutilisation);  
 }
Roy Longbottom
  • 1,192
  • 1
  • 6
  • 8
1

Ideally, as the comment under your question mentioned, you should isolate the piece of code you are trying to measure inside main and just use the unix time command line tool, which reports user and system time.

If you are unable to do that, consider looking at the source code for time and potentially using the same technique to benchmark your code.

merlin2011
  • 71,677
  • 44
  • 195
  • 329
1

I think you need to use clock_gettime() with the following clocks CLOCK_PROCESS_CPUTIME_ID or CLOCK_THREAD_CPUTIME_ID. They give amount of CPU time consumed by a process/thread.

CLOCK_PROCESS_CPUTIME_ID
  High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
  Thread-specific CPU-time clock.

Reference:

I think the advice that gives merlin2011 is infeasible in many cases since isolating might take lots of efforts while adding two lines of code with clock_gettime() is quite practical. You even can wrap calls to clock_gettime() in a class.

Community
  • 1
  • 1