From 331ecd5665fda1c2ca955ca1a3c3785a28c17cd5 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Tue, 17 Aug 2021 09:10:05 +0700 Subject: [PATCH] ``: optimize `chrono::steady_clock::now()` (#2086) Co-authored-by: Bruce Dawson Co-authored-by: Alex Guteniev --- stl/inc/chrono | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index b4b5f2b00..089df2416 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -691,14 +691,24 @@ namespace chrono { const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot const long long _Ctr = _Query_perf_counter(); static_assert(period::num == 1, "This assumes period::num == 1."); - // Instead of just having "(_Ctr * period::den) / _Freq", - // the algorithm below prevents overflow when _Ctr is sufficiently large. - // It assumes that _Freq * period::den does not overflow, which is currently true for nano period. - // It is not realistic for _Ctr to accumulate to large values from zero with this assumption, - // but the initial value of _Ctr could be large. - const long long _Whole = (_Ctr / _Freq) * period::den; - const long long _Part = (_Ctr % _Freq) * period::den / _Freq; - return time_point(duration(_Whole + _Part)); + // 10 MHz is a very common QPC frequency on modern PCs. Optimizing for + // this specific frequency can double the performance of this function by + // avoiding the expensive frequency conversion path. + constexpr long long _TenMHz = 10'000'000; + if (_Freq == _TenMHz) { + static_assert(period::den % _TenMHz == 0, "It should never fail."); + constexpr long long _Multiplier = period::den / _TenMHz; + return time_point(duration(_Ctr * _Multiplier)); + } else { + // Instead of just having "(_Ctr * period::den) / _Freq", + // the algorithm below prevents overflow when _Ctr is sufficiently large. + // It assumes that _Freq * period::den does not overflow, which is currently true for nano period. + // It is not realistic for _Ctr to accumulate to large values from zero with this assumption, + // but the initial value of _Ctr could be large. + const long long _Whole = (_Ctr / _Freq) * period::den; + const long long _Part = (_Ctr % _Freq) * period::den / _Freq; + return time_point(duration(_Whole + _Part)); + } } };