I am trying to understand the precision of the gettimeofday() system call. Here's my program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
struct timeval t;
int prev = 0;
for (int i = 0; i < atoi(argv[1]); i++)
{
gettimeofday(&t, NULL);
printf("secs: %ld, nmicro_secs: %d, delta: %d\n", t.tv_sec, t.tv_usec, t.tv_usec - prev);
prev = t.tv_usec;
sleep(1);
}
return 0;
}
The output if I run this program (./a.out 10) is,
secs: 1643494972, nmicro_secs: 485698, delta: 485698
secs: 1643494973, nmicro_secs: 490785, delta: 5087
secs: 1643494974, nmicro_secs: 491121, delta: 336
secs: 1643494975, nmicro_secs: 494810, delta: 3689
secs: 1643494976, nmicro_secs: 500034, delta: 5224
secs: 1643494977, nmicro_secs: 501143, delta: 1109
secs: 1643494978, nmicro_secs: 506397, delta: 5254
secs: 1643494979, nmicro_secs: 509905, delta: 3508
secs: 1643494980, nmicro_secs: 510637, delta: 732
secs: 1643494981, nmicro_secs: 513451, delta: 2814
The seconds column seems to reconcile with the sleep of 1 secs. Can someone please explain what's going on with the values in micro seconds column? It looks like the jumps from sleep to sleep are ~ 1 millisecond.
You are calculating the difference between two consecutive calls only using the
.tv_usecfield. In other words, you are discarding the.tv_secfield, and therefore if the first measurement yields.tv_sec=1, .tv_usec=500000(meaning 1.5s since epoch) and the second one yields.tv_sec=2, .tv_usec=500000(meaning 2.5s since epoch) yourdeltawould be exactly0, which is wrong.You have to take into account the entire value:
t.tv_sec * 1000000 + t.tv_usec. Only then you can calculate a meaningful difference. Note that you will need a type larger thanintto hold this value. Something likeuintmax_tshould be adequate. Or, as @zwol suggests in the comments, two differentstruct timevalif you want to calculate the difference without an intermediate type.In any case, none of what you are doing will tell you the precision of
gettimeofday, which is a different thing. Sleeping between two syscalls will make your process inactive for a not-so-deterministic amount of time.