blob: eda3f03bbcd335f571509728b6cf6d551c545525 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "clock.h"
#include <util/system/hp_timer.h>
#include <library/cpp/yt/assert/assert.h>
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
// Re-calibrate every 1B CPU ticks.
constexpr auto CalibrationCpuPeriod = 1'000'000'000;
struct TCalibrationState
{
TCpuInstant CpuInstant;
TInstant Instant;
};
double GetMicrosecondsToTicks()
{
static const auto MicrosecondsToTicks = static_cast<double>(NHPTimer::GetCyclesPerSecond()) / 1'000'000;
return MicrosecondsToTicks;
}
double GetTicksToMicroseconds()
{
static const auto TicksToMicroseconds = 1.0 / GetMicrosecondsToTicks();
return TicksToMicroseconds;
}
TCalibrationState GetCalibrationState(TCpuInstant cpuInstant)
{
thread_local TCalibrationState State;
if (State.CpuInstant + CalibrationCpuPeriod < cpuInstant) {
State.CpuInstant = cpuInstant;
State.Instant = TInstant::Now();
}
return State;
}
TCalibrationState GetCalibrationState()
{
return GetCalibrationState(GetCpuInstant());
}
TDuration CpuDurationToDuration(TCpuDuration cpuDuration, double ticksToMicroseconds)
{
// TDuration is unsigned and thus does not support negative values.
if (cpuDuration < 0) {
return TDuration::Zero();
}
return TDuration::MicroSeconds(static_cast<ui64>(cpuDuration * ticksToMicroseconds));
}
TCpuDuration DurationToCpuDuration(TDuration duration, double microsecondsToTicks)
{
return static_cast<TCpuDuration>(duration.MicroSeconds() * microsecondsToTicks);
}
TInstant GetInstant()
{
auto cpuInstant = GetCpuInstant();
auto state = GetCalibrationState(cpuInstant);
YT_ASSERT(cpuInstant >= state.CpuInstant);
return state.Instant + CpuDurationToDuration(cpuInstant - state.CpuInstant, GetTicksToMicroseconds());
}
TDuration CpuDurationToDuration(TCpuDuration cpuDuration)
{
return CpuDurationToDuration(cpuDuration, GetTicksToMicroseconds());
}
TCpuDuration DurationToCpuDuration(TDuration duration)
{
return DurationToCpuDuration(duration, GetMicrosecondsToTicks());
}
TInstant CpuInstantToInstant(TCpuInstant cpuInstant)
{
// TDuration is unsigned and does not support negative values,
// thus we consider two cases separately.
auto state = GetCalibrationState();
return cpuInstant >= state.CpuInstant
? state.Instant + CpuDurationToDuration(cpuInstant - state.CpuInstant, GetTicksToMicroseconds())
: state.Instant - CpuDurationToDuration(state.CpuInstant - cpuInstant, GetTicksToMicroseconds());
}
TCpuInstant InstantToCpuInstant(TInstant instant)
{
// See above.
auto state = GetCalibrationState();
return instant >= state.Instant
? state.CpuInstant + DurationToCpuDuration(instant - state.Instant, GetMicrosecondsToTicks())
: state.CpuInstant - DurationToCpuDuration(state.Instant - instant, GetMicrosecondsToTicks());
}
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT
|