High Definition Clock in VS2013

I'm looking for a cross-platform clock with high resolution, high accuracy and relatively low performance (in order of importance).

I tried:

//using namespace std::chrono;
//typedef std::chrono::high_resolution_clock Clock;

using namespace boost::chrono;
typedef boost::chrono::high_resolution_clock Clock;
auto now = Clock::now().time_since_epoch();
std::size_t secs = duration_cast<seconds>(now).count();
std::size_t nanos = duration_cast<nanoseconds>(now).count() % 1000000000;
std::time_t tp = (std::time_t) secs;
std::string mode;
char timestamp[] = "yyyymmdd HH:MM:SS";
char format[] = "%Y%m%d %H:%M:%S";

strftime(timestamp, 80, format, std::localtime(&tp)); // Takes 12 microseconds
std::string output = timestamp + "." + std::to_string(nanos);

      

After some trials and testing: The original std :: chrono :: high_resolution_clock is a typedef for system_clock and has an accuracy of roughly 1 millisecond. Boost :: chrono :: high_resolution_clock uses Query_Performance_Counter for Windows and has high resolution and precision. Unfortunately, Clock :: now () returns the time from the moment it was loaded and now (). Time_since_epoch () does not return the epoch time (it also returns the time since loading).

Do not mind using security devices for different solutions on different platforms (requires VS2013 and Linux). Most likely save now and do the processing in a separate / low priority thread.

Is there a cross-platform, high-performance, high-precision, user-friendly timer?

Is boost :: chrono :: high_resolution_clock :: now (). time_since_epoch () working as intended? This does not give time since the last era. This only gives the time since the last download. Is there a way to convert this now () to seconds from epoch.

+3


source to share


1 answer


I think the best way to do this is to implement a new clock type that models the requirement Clock

in the C ++ 11/14 standard.

The windows function GetSystemTimePreciseAsFileTime

can be used as the basis for Windows clock. I believe this function returns the time in units of 100 nanoseconds since the start of the window epoch. If I'm wrong, just change the definition period

to match.

struct windows_highres_clock
{
    // implement Clock concept
    using rep = ULONGLONG;
    using period = std::ratio<1, 10000000>;
    using duration = std::chrono::duration<rep, period>;
    using time_point = std::chrono::time_point<windows_highres_clock, duration>;

    static constexpr const bool is_steady = true;

    static time_point now() noexcept {
        FILETIME ft = { 0, 0 };
        GetSystemTimePreciseAsFileTime(&ft);
        ULARGE_INTEGER stamp { { ft.dwLowDateTime, ft.dwHighDateTime } };
        return time_point { duration { stamp.QuadPart } };
    }
};

      

If you want to continue implementing the TrivalClock concept on top of it, this should work. Just follow the instructions at http://cppreference.com

The provision of the from_time_t and to_time_t functions will complete and allow you to use this clock for both representing time and representing date and time.

example of use:

windows_highres_clock clock;
auto t0 = clock.now();
sleep(1);
auto t1 = clock.now();
auto diff = t1 - t0;
auto ms = std::chrono::duration_cast<chrono::milliseconds>(diff);
cout << "waited for " << ms.count() << " milliseconds\n";

      



Output example:

waited for 1005 milliseconds

      

for non-Windows systems, the system_clock is usually sufficient, but you can write a similar clock for each system using your own synchronization mechanisms.

FYI:

Here's a portable piece of code that you can use to check the clock resolution. The any_clock class is a polymorphic container that can contain any clock-like object. It always returns its timestamps as microseconds from the epoch.

// create some syntax to help specialise the any_clock
template<class Clock> struct of_type {};

// polymorphic clock container
struct any_clock
{

    template<class Clock>
    any_clock(of_type<Clock>)
    : _ptr { new model<Clock> {} }
    {}

    std::chrono::microseconds now() const {
        return _ptr->now();
    }

    using duration = std::chrono::microseconds;

private:
    struct concept {
        virtual ~concept() = default;
        virtual duration now() const noexcept = 0;
    };
    template<class Clock>
    struct model final : concept {
        duration now() const noexcept final {
            return std::chrono::duration_cast<std::chrono::microseconds>(Clock::now().time_since_epoch());
        }
    };
    unique_ptr<concept> _ptr;
};

int main(int argc, const char * argv[])
{
    any_clock clocks[] = {
         { of_type<windows_highres_clock>() },
         { of_type<std::chrono::high_resolution_clock>() },
         { of_type<std::chrono::system_clock>() }
    };

    static constexpr size_t nof_clocks = std::extent<decltype(clocks)>::value;
    any_clock::duration t0[nof_clocks];
    any_clock::duration t1[nof_clocks];

    for (size_t i = 0 ; i < nof_clocks ; ++i) {
        t0[i] = clocks[i].now();
    }
    sleep(1);
    for (size_t i = 0 ; i < nof_clocks ; ++i) {
        t1[i] = clocks[i].now();
    }
    for (size_t i = 0 ; i < nof_clocks ; ++i) {
        auto diff = t1[i] - t0[i];
        auto ms = std::chrono::duration_cast<chrono::microseconds>(diff);
        cout << "waited for " << ms.count() << " microseconds\n";
    }
    return 0;
}

      

-1


source







All Articles