[*] added more win32 steady time clock, frequency-based fast paths

This commit is contained in:
Reece Wilson 2023-09-09 13:58:14 +01:00
parent cf7be329d6
commit e7ec875851

View File

@ -23,26 +23,37 @@ struct steady_clock_fast
using duration = std::chrono::nanoseconds;
using time_point = _CHRONO time_point<steady_clock_fast>;
static constexpr bool is_steady = true;
static_assert(period::num == 1, "This assumes period::num == 1.");
_NODISCARD static time_point now() noexcept
{ // get current time
static const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot
{
static const long long _Freq = _Query_perf_frequency();
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.
// 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.
if (_Freq == 10000000)
{
return time_point(duration(_Ctr * 100));
}
else if (_Freq == 1000000)
{
return time_point(duration(_Ctr * 1000));
}
else if (_Freq == 100000)
{
return time_point(duration(_Ctr * 10000));
}
else if (_Freq == 100000000)
{
return time_point(duration(_Ctr * 10));
}
else if (_Freq == 1000000000)
{
return time_point(duration(_Ctr));
}
else
{
// 6 branches: the default threshold for most jit and language compiler backends to decide to pick a jump table, if the values were in a close range
// otherwise, back to a tree of paths. either way, im sure 6 if elses are faster than grug math with large numbers, modulus, division, and multiplication
const long long _Whole = (_Ctr / _Freq) * period::den;
const long long _Part = (_Ctr % _Freq) * period::den / _Freq;
return time_point(duration(_Whole + _Part));