Howard E. Hinnant
2016-07-09
Creative
Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.

<chrono> Clock Survey

This survey shows you how to discover the properties of the three <chrono> clocks:

Here is code to discover each clock's properties:

#include <climits>
#include <chrono>
#include <cstddef>
#include <cstdlib>
#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
#include <type_traits>

template <typename T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}

template <class Clock>
void
stats(std::string const& msg)
{
    std::cout << msg << '\n';
    const std::size_t bits = CHAR_BIT * sizeof(typename Clock::rep);
    std::cout << "    rep is " << type_name<typename Clock::rep>() << " : "
              << bits << " bits\n";
    std::cout << "    period is " << Clock::period::num << '/'
              << Clock::period::den << '\n';
    std::cout << "    is_steady is " << Clock::is_steady << '\n';
}

int
main()
{
    using namespace std::chrono;
    stats<system_clock>("system_clock");
    stats<steady_clock>("steady_clock");
    stats<high_resolution_clock>("high_resolution_clock");
    if (std::is_same<high_resolution_clock, system_clock>::value)
        std::cout << "high_resolution_clock is the same type as system_clock\n";
    if (std::is_same<high_resolution_clock, steady_clock>::value)
        std::cout << "high_resolution_clock is the same type as steady_clock\n";
    if (std::is_same<system_clock, steady_clock>::value)
        std::cout << "system_clock is the same type as steady_clock\n";
}

There are three implementations of <chrono> that I am aware of:

The results are (I've taken minor liberities with the formatting):

libc++:

system_clock
    rep is long long : 64 bits
    period is 1/1,000,000
    is_steady is 0

steady_clock
    rep is long long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock
    rep is long long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock is the same type as steady_clock

libstdc++:

system_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 0

steady_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 0

high_resolution_clock is the same type as system_clock

VS:

system_clock
    rep is __int64 : 64 bits
    period is 1/10,000,000
    is_steady is 0

steady_clock
    rep is __int64 : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock
    rep is __int64 : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock is the same type as steady_clock

There exist online compilers for each of these implementations, and so you can check these results for yourself, on each of these three platforms.

I have further found that each implementation of std::chrono::system_clock is measuring Unix Time. That is, they count non-leap-seconds since 1970-01-01 00:00:00 UTC, except with a precision as noted by the survey above. You can confirm this yourself with the software at this link.