C Tutorial: Use Linux's high resolution clock

Note: The clock_gettime system call described here is not supported by OS X.

Clock_gettime

The clock_gettime system call is a successor to the gettimeofday system call with a few key changes: higher precision and the ability to request specific clocks. It fills in a structure containing two fields: a seconds and a nanosecond count of the time since the Epoch (00:00 1 January, 1970 UTC). This is similar to the struct timeval that gettimeofday used except that the microsecond field is now replaced with a nanosecond field.

struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };

The clock_gettime system call has the following usage:

#include <time.h> int clock_gettime(clockid_t clk_id, struct timespec *tp);

The second parameter is the time structure that will be filled in by the system call to contain the value of the clock. The first parameter, clock ID, allows you to specify the clock you are interested in using. The following are available:

clock ID meaning
CLOCK_REALTIME System-wide real-time clock. This clock is supported by all implementations and returns the number of seconds and nanoseconds since the Epoch. This clock can be set via clock_settime but doing so requires appropriate privileges. When the system time is changed, timers that measure relative intervals are not affected but timers for absolute point in times are.
CLOCK_REALTIME_COARSE (Linux-specific) Faster than CLOCK_REALTIME but not as accurate.
CLOCK_MONOTONIC Represents monotonic time since some unspecified starting point. This clock cannot be set.
CLOCK_MONOTONIC_RAW (Linux-specific) Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.
CLOCK_MONOTONIC_COARSE (Linux-specific) Like CLOCK_MONOTONIC but faster and not as accurate.
CLOCK_PROCESS_CPUTIME_ID High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID Thread-specific CPU-time clock.

As with gettimeofday, the resolution depends on the implementation, so do not always expect to get nanosecond precision. The clock_getres system call returns the resolution of the specified clock. This is informational data since you do not need to apply any scaling factors to data returned by clock_gettime: the values are in seconds and nanoseconds.

#include <time.h> int clock_getres(clockid_t clk_id, struct timespec *res);

For example, if a clock's resolution is 1024 Hz (1/1,024 second), then the resulting resolution is 976562.5 nanoseconds, which will be reported by clock_getres as 976562.

Which clock to use

For getting the system's idea of the time of day (in seconds since the Epoch), one should use clock_gettime(CLOCK_REALTIME, &tp).

For measuring elapsed time, CLOCK_MONOTONIC is recommended. This clock will not necessarily reflect the time of day but, unlike CLOCK_REALTIME, it is guaranteed to always be linearly increasing (although not necessarily between reboots). CLOCK_MONOTONIC is affected by adjustments caused by the Network Time Protocol (NTP) daemon. However, NTP adjustments will not cause this clock to jump; it's rate might be adjusted to compensate for clock drift. CLOCK_REALTIME, on the other hand, may leap forward or even backward after a time adjustment.

CLOCK_MONOTONIC_RAW is available only on some Linux kernels and the tick rate will never be adjusted by NTP. This is fine for short programs but a clock drift over longer periods of time may produce inaccurate results.

The CLOCK_PROCESS_CPU_TIME_ID clock measures only the CPU time consumed by the process. If the kernel puts the process to sleep, the time it spends waiting is not counted. If a process has multiple threads, CLOCK_THREAD_CPUTIME_ID is similar but measures only the CPU time spent on the thread that is making the request.

Example

To compile a program that uses clock_gettime, you need to link with librt.a (the real-time library) by specifying -lrt on your compile line.

This example marks the start time by getting the value of CLOCK_MONOTONIC. The process then sleeps for a second and marks the stop time by getting the value of CLOCK_MONOTONIC a second time. It then does the same thing again but uses CLOCK_PROCESS_CPUTIME_ID. Since the CPU is not used for the time that the process is sleeping, the results are substantially shorter.

/* gettime - get time via clock_gettime N.B.: OS X does not support clock_gettime Paul Krzyzanowski */ #include <stdio.h> /* for printf */ #include <stdint.h> /* for uint64 definition */ #include <stdlib.h> /* for exit() definition */ #include <time.h> /* for clock_gettime */ #define BILLION 1000000000L int localpid(void) { static int a[9] = { 0 }; return a[0]; } main(int argc, char **argv) { uint64_t diff; struct timespec start, end; int i; /* measure monotonic time */ clock_gettime(CLOCK_MONOTONIC, &start); /* mark start time */ sleep(1); /* do stuff */ clock_gettime(CLOCK_MONOTONIC, &end); /* mark the end time */ diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec; printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff); /* now re-do this and measure CPU time */ /* the time spent sleeping will not count (but there is a bit of overhead */ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); /* mark start time */ sleep(1); /* do stuff */ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); /* mark the end time */ diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec; printf("elapsed process CPU time = %llu nanoseconds\n", (long long unsigned int) diff); exit(0); }

Download this file

Save this file by control-clicking or right clicking the download link and then saving it as gettime.c.

Compile this program via:

gcc -o gettime gettime.c -lrt

If you don't have gcc, You may need to substitute the gcc command with cc or another name of your compiler.

Run the program:

./gettime

Recommended

The Practice of Programming

 

The C Programming Language

 

The UNIX Programming Environment