Search code examples
clinuxclock

Do CLOCK_MONOTONIC and CLOCK_MONOTONIC_COARSE have the same base?


The man page for clock_gettime() describes CLOCK_MONOTONIC_COARSE as:

A faster but less precise version of CLOCK_MONOTONIC. Use when you need very fast, but not fine-grained timestamps.

What does it mean for one to be a "version of" the other?

Can I validly compare one to the other, assuming I truncate a CLOCK_MONOTONIC value to the same precision as the coarse one?


Solution

  • The short answer is YES (at least for Linux!), you can compare them, compute delays, etc...

    The precision would be that of the less precise, most probably COARSE one.

    See this short program:

    #include <time.h>
    #include <stdio.h>
    
    int main()
    {
        int ret;
        struct  timespec res;
    
        ret = clock_getres(CLOCK_MONOTONIC, &res);
        if (0 != ret)
            return ret;
        printf("CLOCK_MONOTONIC resolution is: %ld sec, %ld nsec\n", (long)res.tv_sec, (long)res.tv_nsec);
    
        ret = clock_getres(CLOCK_MONOTONIC_COARSE, &res);
        if (0 != ret)
            return ret;
        printf("CLOCK_MONOTONIC_COARSE resolution is: %ld sec, %ld nsec\n", (long)res.tv_sec, (long)res.tv_nsec);
    
        return 0;
    }
    

    It returns (Ubuntu 20.04 - 64bits - kernel 5.4)

    CLOCK_MONOTONIC resolution is: 0 sec, 1 nsec
    CLOCK_MONOTONIC_COARSE resolution is: 0 sec, 4000000 nsec
    

    So MONOTONIC has nanosecond precision, and COARSE has 4 milliseconds precision.

    Unlike above comment, I would on the contrary recommend to use the COARSE version when the timings you need allow.

    Calls to the clock are so frequent in user programs that they have a place in vDSO

    When you use COARSE versions, you have exactly zero system call, and it is as fast as your machine can run a few instructions. Thanks to vDSO your program fully stays in "userland" during the call with COARSE. With other types of clocks, you will have some system calls, and potential access to hardware. So at least a switch to "kernel" and back to "userland".

    This of course has zero importance if your program just needs a dozen of calls, but it can be a huge time saver if, on the contrary, the program relies heavily on the clock. That is why, vDSO is there in the first place: performance!

    • Define first what is the accuracy you need for your timings. Is second enough, do you need milli second, micro, etc...
    • Have in mind, unless you are tinkering with RT systems, that time is a relative value! Imagine you called clock_gettime, and immediately after returning your thread gets interrupted for any kernel business: what is the accuracy you get? That is exactly the famous question that defeated HAL in 2001: A space Odyssey: "what time is it?".
    • From that you can derive what is the type of clock you need.
    • You can mix MONOTONIC and the COARSE version of it and still compute delays or compare (that was the original question). But of course the precision is that of the less precise.
    • The monotonics are best suited to do time delays and do comparisons since they don't depend on the real time (as your watch displays). They don't change when the user changes the actual time.
    • On the contrary, if you need to display at what time (meaningful for the user) an event occurred, don't use monotonic!