clock.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. YT_PREVENT_TLS_CACHING TCalibrationState GetCalibrationState(TCpuInstant cpuInstant)
  25. {
  26. thread_local TCalibrationState State;
  27. if (State.CpuInstant + CalibrationCpuPeriod < cpuInstant) {
  28. State.CpuInstant = cpuInstant;
  29. State.Instant = TInstant::Now();
  30. }
  31. return State;
  32. }
  33. TCalibrationState GetCalibrationState()
  34. {
  35. return GetCalibrationState(GetCpuInstant());
  36. }
  37. TDuration CpuDurationToDuration(TCpuDuration cpuDuration, double ticksToMicroseconds)
  38. {
  39. // TDuration is unsigned and thus does not support negative values.
  40. if (cpuDuration < 0) {
  41. return TDuration::Zero();
  42. }
  43. return TDuration::MicroSeconds(static_cast<ui64>(cpuDuration * ticksToMicroseconds));
  44. }
  45. TCpuDuration DurationToCpuDuration(TDuration duration, double microsecondsToTicks)
  46. {
  47. return static_cast<TCpuDuration>(duration.MicroSeconds() * microsecondsToTicks);
  48. }
  49. TInstant GetInstant()
  50. {
  51. auto cpuInstant = GetCpuInstant();
  52. auto state = GetCalibrationState(cpuInstant);
  53. YT_ASSERT(cpuInstant >= state.CpuInstant);
  54. return state.Instant + CpuDurationToDuration(cpuInstant - state.CpuInstant, GetTicksToMicroseconds());
  55. }
  56. TDuration CpuDurationToDuration(TCpuDuration cpuDuration)
  57. {
  58. return CpuDurationToDuration(cpuDuration, GetTicksToMicroseconds());
  59. }
  60. TCpuDuration DurationToCpuDuration(TDuration duration)
  61. {
  62. return DurationToCpuDuration(duration, GetMicrosecondsToTicks());
  63. }
  64. TInstant CpuInstantToInstant(TCpuInstant cpuInstant)
  65. {
  66. // TDuration is unsigned and does not support negative values,
  67. // thus we consider two cases separately.
  68. auto state = GetCalibrationState();
  69. return cpuInstant >= state.CpuInstant
  70. ? state.Instant + CpuDurationToDuration(cpuInstant - state.CpuInstant, GetTicksToMicroseconds())
  71. : state.Instant - CpuDurationToDuration(state.CpuInstant - cpuInstant, GetTicksToMicroseconds());
  72. }
  73. TCpuInstant InstantToCpuInstant(TInstant instant)
  74. {
  75. // See above.
  76. auto state = GetCalibrationState();
  77. return instant >= state.Instant
  78. ? state.CpuInstant + DurationToCpuDuration(instant - state.Instant, GetMicrosecondsToTicks())
  79. : state.CpuInstant - DurationToCpuDuration(state.Instant - instant, GetMicrosecondsToTicks());
  80. }
  81. ////////////////////////////////////////////////////////////////////////////////
  82. } // namespace NYT