Andres Jaan Tack
Andres Jaan Tack

Reputation: 23024

Why are gettimeofday() intervals occasionally negative?

I have an experimental library whose performance I'm trying to measure. To do this, I've written the following:

struct timeval begin;
gettimeofday(&begin, NULL);
{
    // Experiment!
}
struct timeval end;
gettimeofday(&end, NULL);

// Print the time it took!
std::cout << "Time: " << 100000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) << std::endl;

Occasionally, my results include negative timings, some of which are nonsensical. For instance:

Time: 226762
Time: 220222
Time: 210883
Time: -688976

What's going on?

Upvotes: 6

Views: 9006

Answers (5)

sdmello
sdmello

Reputation: 429

You took care of the negative value but it still isn't correct. The difference between the millisecond variables is erroneous, say we have begin and end times as 1.100s and 2.051s. By the accepted answer this would be an elapsed time of 1.049s which is incorrect.

The below code takes care of the cases where there is only a difference of milliseconds but not seconds and the case where the milliseconds value overflows.

if(end.tv_sec==begin.tv_sec)
printf("Total Time =%ldus\n",(end.tv_usec-begin.tv_usec));
else
printf("Total Time =%ldus\n",(end.tv_sec-begin.tv_sec-1)*1000000+(1000000-begin.tv_usec)+end.tv_usec);

Upvotes: 5

deft_code
deft_code

Reputation: 59337

The posix realtime libraries are better suited for measurement of high accuracy intervals. You really don't want to know the current time. You just want to know how long it has been between two points. That is what the monotonic clock is for.

struct timespec begin;
clock_gettime( CLOCK_MONOTONIC, &begin );
{
    // Experiment!
}
struct timespec end;
clock_gettime(CLOCK_MONOTONIC, &end );

// Print the time it took!
std::cout << "Time: " << double(end.tv_sec - begin.tv_sec) + (end.tv_nsec - begin.tv_nsec)/1000000000.0 << std::endl;

When you link you need to add -lrt.

Using the monotonic clock has several advantages. It often uses the hardware timers (Hz crystal or whatever), so it is often a faster call than gettimeofday(). Also monotonic timers are guaranteed to never go backwards even if ntpd or a user is goofing with the system time.

Upvotes: 5

Noone
Noone

Reputation: 1

do

$ time ./proxy-application

next time

Upvotes: -1

ariels - IGNORE AI
ariels - IGNORE AI

Reputation: 551

std::cout << "Time: " << 100000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) << std::endl;

As noted, there are 1000000 usec in a sec, not 100000.

More generally, you may need to be aware of the instability of timing on computers. Processes such as ntpd can change clock times, leading to incorrect delta times. You might be interested in POSIX facilities such as timer_create.

Upvotes: 3

Michael Ulm
Michael Ulm

Reputation: 802

You've got a typo. Corrected last line (note the number of 0s):

std::cout << "Time: " << 1000000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) << std::endl;

BTW, timersub is a built in method to get the difference between two timevals.

Upvotes: 6

Related Questions