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 withclock_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 describesCLOCK_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 theclock_gettime()
function instead of the obsolescentgettimeofday()
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
What Is Wrong with Making a Unit Test a Friend of the Class It Is Testing
How to Use a Lambda Expression as a Template Parameter
How to Catch Out of Memory Exception in C++
C++ Frontend Only Compiler (Convert C++ to C)
Convert First Letter in String to Uppercase
What Strategies Have You Used to Improve Build Times on Large Projects
Aliasing Struct and Array the C++ Way
Brute-Force, Single-Threaded Prime Factorization
Implementing Component System from Unity in C++
Inet_Pton': Identifier Not Found
Print MACro Values Without Knowing the Amount of MACros
Partial Ordering with Function Template Having Undeduced Context
How to Access a Global Variable Within a Local Scope
"Winapifamily.H: No Such File or Directory" When Compiling Sdl in Code::Blocks
How to Get Python Exception Text
C++11 Variadic Printf Performance
How to Generate a Random Number Using the C++11 Standard Library