89

What is the best way to time a code section with high resolution and portability?

/* Time from here */
ProcessIntenseFunction();
/* to here. */

printf("Time taken %d seconds %d milliseconds", sec, msec);

Is there a standard library that would have a cross-platform solution?

Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
lillq
  • 14,758
  • 20
  • 53
  • 58

6 Answers6

150

I think this should work:

#include <time.h>

clock_t start = clock(), diff;
ProcessIntenseFunction();
diff = clock() - start;

int msec = diff * 1000 / CLOCKS_PER_SEC;
printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000);
Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
  • 14
    This is actually good since it gives you CPU time rather than elapsed time (elapsed time could be affected by other processes). Just keep in mind that a figure of 10 secs doesn't necessarily mean it will run in 10 secs elapsed time, since there may be I/O considerations. This measures CPU **ONLY**. – paxdiablo Jan 20 '09 at 01:22
  • 2
    I used this hundreds of times and is the the best/easiest solution for this question – Gerhard Jan 21 '09 at 06:18
  • what's the time resolution of clock()? and why diff*1000? – dingx Oct 13 '11 at 02:03
  • 5
    you can even stuff this all into a macro if you're timing multiple things often: #define timing(a) start=clock(); a; diff = clock() - start; msec = diff * 1000 / CLOCKS_PER_SEC; printf("msecs: %d\n",msec); and then invoke: timing(IntenseFunc1()) – eqzx Feb 26 '12 at 19:03
  • 4
    clock_t is usually a long and CLOCKS_PER_SEC is 1000000. In this case, difference of more than 4 seconds will give you overflow and strange results – Begelfor Mar 05 '14 at 13:22
  • 2
    @paxdiablo I get completely equivalent results with this as with gettimeofday(), not sure what you are saying here. – user3467349 Oct 21 '14 at 21:47
  • 1
    If you omit `* 1000` in order to get seconds, remember to cast `diff` to float before dividing it by `CLOCKS_PER_SEC`. That has taken me a few minutes to find out. – SimonH Jun 17 '16 at 18:44
  • 1
    @paxdiablo what do you mean with CPU time and I/O considerations,does it mean that if my function that I want to time reads from and writes to a file (IO action), the time taken by reading and writing will not be measured? – fangio Nov 24 '16 at 17:53
  • Why is this accurate? CPU clock per sec are very variable! CPU GHz varies a lot unless I deliberately disable it in power options. What am I missing here? – CoR Dec 16 '20 at 21:04
24

gettimeofday() will probably do what you want.

If you're on Intel hardware, here's how to read the CPU real-time instruction counter. It will tell you the number of CPU cycles executed since the processor was booted. This is probably the finest-grained, lowest overhead counter you can get for performance measurement.

Note that this is the number of CPU cycles. On linux you can get the CPU speed from /proc/cpuinfo and divide to get the number of seconds. Converting this to a double is quite handy.

When I run this on my box, I get

11867927879484732
11867927879692217
it took this long to call printf: 207485

Here's the Intel developer's guide that gives tons of detail.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}
Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
6

gettimeofday will return time accurate to microseconds within the resolution of the system clock. You might also want to check out the High Res Timers project on SourceForge.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
2

If you don't want CPU time then I think what you're looking for is the timeval struct.

I use the below for calculating execution time:

int timeval_subtract(struct timeval *result,                                                                                                                                        
                     struct timeval end,                                                                                                                                                 
                     struct timeval start)                                                                                                                                               
{                                                                                                                                                                                   
        if (start.tv_usec < end.tv_usec) {                                                                                                                                          
                int nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;                                                                                                             
                end.tv_usec -= 1000000 * nsec;                                                                                                                                      
                end.tv_sec += nsec;                                                                                                                                                 
        }                                                                                                                                                                           
        if (start.tv_usec - end.tv_usec > 1000000) {                                                                                                                                
                int nsec = (end.tv_usec - start.tv_usec) / 1000000;                                                                                                                 
                end.tv_usec += 1000000 * nsec;                                                                                                                                      
                end.tv_sec -= nsec;                                                                                                                                                 
        }                                                                                                                                                                           

        result->tv_sec = end.tv_sec - start.tv_sec;                                                                                                                                 
        result->tv_usec = end.tv_usec - start.tv_usec;                                                                                                                              

        return end.tv_sec < start.tv_sec;                                                                                                                                           
}                                                                                                                                                                                   

void set_exec_time(int end)                                                                                                                                                         
{                                                                                                                                                                                   
        static struct timeval time_start;                                                                                                                                           
        struct timeval time_end;                                                                                                                                                    
        struct timeval time_diff;                                                                                                                                                   

        if (end) {                                                                                                                                                                  
                gettimeofday(&time_end, NULL);                                                                                                                                      
                if (timeval_subtract(&time_diff, time_end, time_start) == 0) {                                                                                                      
                        if (end == 1)                                                                                                                                               
                                printf("\nexec time: %1.2fs\n",                                                                                                                     
                                        time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));                                                                                       
                        else if (end == 2)                                                                                                                                          
                                printf("%1.2fs",                                                                                                                                    
                                        time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));                                                                                       
                }                                                                                                                                                                   
                return;                                                                                                                                                             
        }                                                                                                                                                                           
        gettimeofday(&time_start, NULL);                                                                                                                                            
}                                                                                                                                                                                   

void start_exec_timer()                                                                                                                                                             
{                                                                                                                                                                                   
        set_exec_time(0);                                                                                                                                                           
}                                                                                                                                                                                   

void print_exec_timer()                                                                                                                                                             
{                                                                                                                                                                                   
        set_exec_time(1);                                                                                                                                                           
}
HDevejian
  • 111
  • 1
  • 5
1

I use SDL_GetTicks from the SDL library.

driAn
  • 3,245
  • 4
  • 41
  • 57
0

High resolution is relative... I was looking at the examples and they mostly cater for milliseconds. However for me it is important to measure microseconds. I have not seen a platform independant solution for microseconds and thought something like the code below will be usefull. I was timing on windows only for the time being and will most likely add a gettimeofday() implementation when doing the same on AIX/Linux.

    #ifdef WIN32
      #ifndef PERFTIME
        #include <windows.h>
        #include <winbase.h>
        #define PERFTIME_INIT unsigned __int64 freq;  QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq);  unsigned __int64 startTime;  unsigned __int64 endTime;  double timeDifferenceInMilliseconds;
        #define PERFTIME_START QueryPerformanceCounter((LARGE_INTEGER *)&startTime);
        #define PERFTIME_END QueryPerformanceCounter((LARGE_INTEGER *)&endTime); timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency);  printf("Timing %fms\n",timeDifferenceInMilliseconds);
    #define PERFTIME(funct) {unsigned __int64 freq;  QueryPerformanceFrequency((LARGE_INTEGER*)&freq);  double timerFrequency = (1.0/freq);  unsigned __int64 startTime;  QueryPerformanceCounter((LARGE_INTEGER *)&startTime);  unsigned __int64 endTime;  funct; QueryPerformanceCounter((LARGE_INTEGER *)&endTime);  double timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency);  printf("Timing %fms\n",timeDifferenceInMilliseconds);}
      #endif
    #else
      //AIX/Linux gettimeofday() implementation here
    #endif

Usage:

PERFTIME(ProcessIntenseFunction());

or

PERFTIME_INIT
PERFTIME_START
ProcessIntenseFunction()
PERFTIME_END
Rohan
  • 31
  • 3