diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/hp_timer.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/hp_timer.cpp')
-rw-r--r-- | util/system/hp_timer.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/util/system/hp_timer.cpp b/util/system/hp_timer.cpp new file mode 100644 index 0000000000..e4c3f21e6b --- /dev/null +++ b/util/system/hp_timer.cpp @@ -0,0 +1,118 @@ +#include "hp_timer.h" + +#include <util/generic/algorithm.h> +#include <util/generic/singleton.h> +#include <util/datetime/cputimer.h> + +using namespace NHPTimer; + +namespace { + struct TFreq { + inline TFreq() + : Freq(InitHPTimer()) + , Rate(1.0 / Freq) + , CyclesPerSecond(static_cast<ui64>(Rate)) + { + } + + static inline const TFreq& Instance() { + return *SingletonWithPriority<TFreq, 1>(); + } + + static double EstimateCPUClock() { + for (;;) { + ui64 startCycle = 0; + ui64 startMS = 0; + + for (;;) { + startMS = MicroSeconds(); + startCycle = GetCycleCount(); + + ui64 n = MicroSeconds(); + + if (n - startMS < 100) { + break; + } + } + + Sleep(TDuration::MicroSeconds(5000)); + + ui64 finishCycle = 0; + ui64 finishMS = 0; + + for (;;) { + finishMS = MicroSeconds(); + + if (finishMS - startMS < 100) { + continue; + } + + finishCycle = GetCycleCount(); + + ui64 n = MicroSeconds(); + + if (n - finishMS < 100) { + break; + } + } + if (startMS < finishMS && startCycle < finishCycle) { + return (finishCycle - startCycle) * 1000000.0 / (finishMS - startMS); + } + } + } + + static double InitHPTimer() { + const size_t N_VEC = 9; + + double vec[N_VEC]; + + for (auto& i : vec) { + i = EstimateCPUClock(); + } + + Sort(vec, vec + N_VEC); + + return 1.0 / vec[N_VEC / 2]; + } + + inline double GetSeconds(const STime& a) const { + return static_cast<double>(a) * Freq; + } + + inline double GetClockRate() const { + return Rate; + } + + inline ui64 GetCyclesPerSecond() const { + return CyclesPerSecond; + } + + const double Freq; + const double Rate; + const ui64 CyclesPerSecond; + }; +} + +double NHPTimer::GetSeconds(const STime& a) noexcept { + return TFreq::Instance().GetSeconds(a); +} + +double NHPTimer::GetClockRate() noexcept { + return TFreq::Instance().GetClockRate(); +} + +ui64 NHPTimer::GetCyclesPerSecond() noexcept { + return TFreq::Instance().GetCyclesPerSecond(); +} + +void NHPTimer::GetTime(STime* pTime) noexcept { + *pTime = GetCycleCount(); +} + +double NHPTimer::GetTimePassed(STime* pTime) noexcept { + STime old(*pTime); + + *pTime = GetCycleCount(); + + return GetSeconds(*pTime - old); +} |