aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/cpu_clock/clock.cpp
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /library/cpp/yt/cpu_clock/clock.cpp
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'library/cpp/yt/cpu_clock/clock.cpp')
-rw-r--r--library/cpp/yt/cpu_clock/clock.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/library/cpp/yt/cpu_clock/clock.cpp b/library/cpp/yt/cpu_clock/clock.cpp
new file mode 100644
index 0000000000..eda3f03bbc
--- /dev/null
+++ b/library/cpp/yt/cpu_clock/clock.cpp
@@ -0,0 +1,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