clock.cpp 2.9 KB

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