Understanding the Different Clocks of Clock_Gettime()

Understanding the different clocks of clock_gettime()

CLOCK_REALTIME reports the actual wall clock time.

CLOCK_MONOTONIC is for measuring relative real time. It advances at the same rate as the actual flow of time but it's not subject to discontinuities from manual or automatic (NTP) adjustments to the system clock.

CLOCK_PROCESS_CPUTIME_ID is for measuring the amount of CPU time consumed by the process.

CLOCK_THREAD_CPUTIME_ID is for measuring the amount of CPU time consumed by the thread. It's supported by modern kernels and glibc since 2.6.12, but on older linux kernels glibc emulates it badly by simply returning the amount of CPU time consumed by the process since the moment the thread was created.

http://man7.org/linux/man-pages/man2/clock_gettime.2.html

Measure time in Linux - time vs clock vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

The problem is that there are several different time functions available in C and C++, and some of them vary in behavior between implementations. There are also a lot of half-answers floating around. Compiling a list of clock functions together with their properties would answer the question properly. For starts let's ask what the relevant properties are that we're looking for. Looking at your post, I suggest:

  • What time is measured by the clock? (real, user, system, or, hopefully not, wall-clock?)
  • What is the precision of the clock? (s, ms, µs, or faster?)
  • After how much time does the clock wrap around? Or is there some mechanism to avoid this?
  • Is the clock monotonic, or will it change with changes in the system time (via NTP, time zone, daylight savings time, by the user, etc.)?
  • How do the above vary between implementations?
  • Is the specific function obsolete, non standard, etc.?

Before starting the list, I'd like to point out that wall-clock time is rarely the right time to use, whereas it changes with time zone changes, daylight savings time changes, or if the wall clock is synchronized by NTP. None of these things are good if you're using the time to schedule events or to benchmark performance. It's only really good for what the name says, a clock on the wall (or desktop).

Here's what I've found so far for clocks in Linux and OS X:

  • time() returns the wall-clock time from the OS, with precision in seconds.
  • clock() seems to return the sum of user and system time. It is present in C89 and later. At one time this was supposed to be the CPU time in cycles, but modern standards like POSIX require CLOCKS_PER_SEC to be 1000000, giving a maximum possible precision of 1 µs. The precision on my system is indeed 1 µs. This clock wraps around once it tops out (this typically happens after ~2^32 ticks, which is not very long for a 1 MHz clock). man clock says that since glibc 2.18 it is implemented with clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) in Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...) provides nanosecond resolution, is monotonic. I believe the 'seconds' and 'nanoseconds' are stored separately, each in 32-bit counters. Thus, any wrap-around would occur after many dozen years of uptime. This looks like a very good clock, but unfortunately it isn't yet available on OS X. POSIX 7 describes CLOCK_MONOTONIC as an optional extension.
  • getrusage() turned out to be the best choice for my situation. It reports the user and system times separately and does not wrap around. The precision on my system is 1 µs, but I also tested it on a Linux system (Red Hat 4.1.2-48 with GCC 4.1.2) and there the precision was only 1 ms.
  • gettimeofday() returns the wall-clock time with (nominally) µs precision. On my system this clock does seem to have µs precision, but this is not guaranteed, because "the resolution of the system clock is hardware dependent". POSIX.1-2008 says that. "Applications should use the clock_gettime() function instead of the obsolescent gettimeofday() function", so you should stay away from it. Linux x86 and implements it as a system call.
  • mach_absolute_time() is an option for very high resolution (ns) timing on OS X. On my system, this does indeed give ns resolution. In principle this clock wraps around, however it is storing ns using a 64-bit unsigned integer, so the wrapping around shouldn't be an issue in practice. Portability is questionable.
  • I wrote a hybrid function based on this snippet that uses clock_gettime when compiled on Linux, or a Mach timer when compiled on OS X, in order to get ns precision on both Linux and OS X.

All of the above exist in both Linux and OS X except where otherwise specified. "My system" in the above is an Apple running OS X 10.8.3 with GCC 4.7.2 from MacPorts.

Finally, here is a list of references that I found helpful in addition to the links above:

  • http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time
  • How to measure the ACTUAL execution time of a C program under Linux?
  • http://digitalsandwich.com/archives/27-benchmarking-misconceptions-microtime-vs-getrusage.html
  • http://www.unix.com/hp-ux/38937-getrusage.html

Update: for OS X, clock_gettime has been implemented as of 10.12 (Sierra). Also, both POSIX and BSD based platforms (like OS X) share the rusage.ru_utime struct field.

Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

CLOCK_REALTIME represents the machine's best-guess as to the current wall-clock, time-of-day time. As Ignacio and MarkR say, this means that CLOCK_REALTIME can jump forwards and backwards as the system time-of-day clock is changed, including by NTP.

CLOCK_MONOTONIC represents the absolute elapsed wall-clock time since some arbitrary, fixed point in the past. It isn't affected by changes in the system time-of-day clock.

If you want to compute the elapsed time between two events observed on the one machine without an intervening reboot, CLOCK_MONOTONIC is the best option.

Note that on Linux, CLOCK_MONOTONIC does not measure time spent in suspend, although by the POSIX definition it should. You can use the Linux-specific CLOCK_BOOTTIME for a monotonic clock that keeps running during suspend.

Any difference between clock_gettime( CLOCK_REALTIME .... ) and time()?

[Note: I used the git master branch and v4.7 for the reference links below, x86 only, as I'm lazy.]

time() is in fact an alias for the equally named syscall, which calls get_seconds, happens at kernel/time/time.c. That syscall uses the get_seconds function to return the UNIX timestamp, which is read from the core timekeeping struct, more precisely from the "Current CLOCK_REALTIME time in seconds" field (xtime_sec).

clock_gettime() is a glibc function in sysdeps\unix\clock_gettime.c, which simply calls gettimeofday if the supplied clock ID is CLOCK_REALTIME, which is again backed by the equally named syscall (source is in the same time.c file, above). This one calls do_gettimeofday, which eventually ends up calling __getnstimeofday64, that queries... the very same xtime_sec field from the same struct as above.

Update:

As @MaximEgorushkin cleverly pointed out, a new vDSO mechanism hijacks (a good sign it is present, if your binary depends on linux-vdso.so.*) the clock_gettime call and redirects it to __vdso_clock_gettime. This one uses a new clock source management framework (gtod - Generic Time Of Day). A call to do_realtime, and it reads from a structure, struct vsyscall_gtod_data's wall_time_sec field. This structure is maintained by update_vsyscall, from the same timekeeper struct as the above.

tl;dr

The answer is: yes, they get the time from the same clock source.

Problem of understanding clock_gettime

Your system clock source is probably set to TSC instead of HPET.

On modern multi-core systems in general, HPET is a newer system that is more accurate and consistent, and TSC is an older system that is more performant.

On openSUSE, you can find out what your current clocksource is by

cat /sys/devices/system/clocksource/clocksource0/current_clocksource

To set your clock source to HPET on openSUSE, do

echo 'hpet' > /sys/devices/system/clocksource/clocksource0/current_clocksource

Further reading:

http://en.wikipedia.org/wiki/HPET

http://en.wikipedia.org/wiki/Time_Stamp_Counter

Using CLOCK_PROCESS_CPUTIME_ID in clock_gettime

In a multi-process environment, processes are constantly migrating from CPU(s) to 'run queue(s)'.

When performance testing an application, it is often convenient to know the amount of time a process has been running on a CPU, while excluding time that the process was waiting for a CPU resource on a 'run queue'.

In the case of this question, where CPU-time is about half of REAL-time, it is likely that other processes were actively competing for CPU time while your process was also running. It appears that your process was fairly successful in acquiring roughly half the CPU resources during its run.

Instead of using CLOCK_PROCESS_CPUTIME_ID, you might consider using CLOCK_REALTIME?

For additional details, see: Understanding the different clocks of clock_gettime()

How are clock_gettime and getrusage related?

There are lots of clocks in Unix and Linux. Some are wall clocks (CLOCK_REALTIME), some are modified wall clocks (CLOCK_MONO, CLOCK_BOOT), and some are CPU time clocks (CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID).

clock_gettime can pull from basically any clock that has a clkid assigned. (Down in the kernel, there's basically code that, for each clkid, defines an appropriate get method for clock_gettime to use.)

I suspect, but have not confirmed, that clock_gettime with one of the CPU-time-related clkids pulls from the same CPU counters as getrusage does.

Answering your questions in turn:

Does one call the other one?

I don't believe so.

Do they both rely on the same underlying mechanism?

I believe so, but I have not confirmed this.

If so what's their greatest common denominator, and by that I mean, what function from the linux kernel are they both calling to get the time?

I'm not sure. (Sorry. My work in all of this has been focused on the wall times, not the CPU times.)

And if they are not relying on the same underlying mechanism then why?

Because the time-related code in the Linux kernel is crazy complicated, and tries to serve a lot of different masters.



Related Topics



Leave a reply



Submit