From 5a085560f319df720472d7ff5f045e2c0f77f28e Mon Sep 17 00:00:00 2001 From: Calcitem Date: Sun, 10 Nov 2019 10:57:47 +0800 Subject: [PATCH] timestat: Add stopwatch --- millgame.pro | 1 + millgame.vcxproj | 5 ++- millgame.vcxproj.filters | 3 ++ src/base/stopwatch.h | 81 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/base/stopwatch.h diff --git a/millgame.pro b/millgame.pro index eb97cbc0..7e48f350 100644 --- a/millgame.pro +++ b/millgame.pro @@ -64,6 +64,7 @@ HEADERS += \ src/base/misc.h \ src/base/sort.h \ src/base/stack.h \ + src/base/stopwatch.h \ src/base/thread.h \ src/ai/search.h \ src/base/zobrist.h \ diff --git a/millgame.vcxproj b/millgame.vcxproj index e2944d2c..287231a2 100644 --- a/millgame.vcxproj +++ b/millgame.vcxproj @@ -122,7 +122,7 @@ Sync $(IntDir) MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_NETWORK_LIB;QT_NETWORKAUTH_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_NETWORK_LIB;QT_NETWORKAUTH_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) false $(IntDir)vc$(PlatformToolsetVersion).pdb MultiThreadedDLL @@ -158,7 +158,7 @@ $(QTDIR) .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_NETWORK_LIB;QT_NETWORKAUTH_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_NETWORK_LIB;QT_NETWORKAUTH_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) msvc $(Configuration)/moc_predefs.h Moc'ing %(Identity)... @@ -455,6 +455,7 @@ + diff --git a/millgame.vcxproj.filters b/millgame.vcxproj.filters index 660fb981..ae34016c 100644 --- a/millgame.vcxproj.filters +++ b/millgame.vcxproj.filters @@ -132,6 +132,9 @@ ai + + base + diff --git a/src/base/stopwatch.h b/src/base/stopwatch.h new file mode 100644 index 00000000..b1f40d15 --- /dev/null +++ b/src/base/stopwatch.h @@ -0,0 +1,81 @@ +#ifndef STOPWATCH_H_ +#define STOPWATCH_H_ + +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +namespace stopwatch { +// An implementation of the 'TrivialClock' concept using the rdtscp instruction. +struct rdtscp_clock { + using rep = std::uint64_t; + using period = std::ratio<1>; + using duration = std::chrono::duration; + using time_point = std::chrono::time_point; + + static auto now() noexcept -> time_point + { +#ifdef _WIN32 + unsigned int ui; + return time_point(duration((static_cast(__rdtscp(&ui))))); +#else + std::uint32_t hi, lo; + __asm__ __volatile__("rdtscp" : "=d"(hi), "=a"(lo)); + return time_point(duration((static_cast(hi) << 32) | lo)); +#endif // WIN32 + } +}; + +// A timer using the specified clock. +template +struct timer { + using time_point = typename Clock::time_point; + using duration = typename Clock::duration; + + timer(const duration duration) noexcept : expiry(Clock::now() + duration) {} + timer(const time_point expiry) noexcept : expiry(expiry) {} + + bool done(time_point now = Clock::now()) const noexcept { + return now >= expiry; + } + + auto remaining(time_point now = Clock::now()) const noexcept -> duration { + return expiry - now; + } + + const time_point expiry; +}; + +template +constexpr auto make_timer(typename Clock::duration duration) -> timer { + return timer(duration); +} + +// Times how long it takes a function to execute using the specified clock. +template +auto time(Func&& function) -> typename Clock::duration { + const auto start = Clock::now(); + function(); + return Clock::now() - start; +} + +// Samples the given function N times using the specified clock. +template +auto sample(Func&& function) -> std::array { + std::array samples; + + for (std::size_t i = 0u; i < N; ++i) { + samples[i] = time(function); + } + + std::sort(samples.begin(), samples.end()); + return samples; +} +} /* namespace stopwatch */ + +#endif // STOPWATCH_H_