clock.cpp 3.0 KB

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