hp_timer.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "hp_timer.h"
  2. #include <util/generic/algorithm.h>
  3. #include <util/generic/singleton.h>
  4. #include <util/datetime/cputimer.h>
  5. using namespace NHPTimer;
  6. namespace {
  7. struct TFreq {
  8. inline TFreq()
  9. : Freq(InitHPTimer())
  10. , Rate(1.0 / Freq)
  11. , CyclesPerSecond(static_cast<ui64>(Rate))
  12. {
  13. }
  14. static inline const TFreq& Instance() {
  15. return *SingletonWithPriority<TFreq, 1>();
  16. }
  17. static double EstimateCPUClock() {
  18. for (;;) {
  19. ui64 startCycle = 0;
  20. ui64 startMS = 0;
  21. for (;;) {
  22. startMS = MicroSeconds();
  23. startCycle = GetCycleCount();
  24. ui64 n = MicroSeconds();
  25. if (n - startMS < 100) {
  26. break;
  27. }
  28. }
  29. Sleep(TDuration::MicroSeconds(5000));
  30. ui64 finishCycle = 0;
  31. ui64 finishMS = 0;
  32. for (;;) {
  33. finishMS = MicroSeconds();
  34. if (finishMS - startMS < 100) {
  35. continue;
  36. }
  37. finishCycle = GetCycleCount();
  38. ui64 n = MicroSeconds();
  39. if (n - finishMS < 100) {
  40. break;
  41. }
  42. }
  43. if (startMS < finishMS && startCycle < finishCycle) {
  44. return (finishCycle - startCycle) * 1000000.0 / (finishMS - startMS);
  45. }
  46. }
  47. }
  48. static double InitHPTimer() {
  49. const size_t N_VEC = 9;
  50. double vec[N_VEC];
  51. for (auto& i : vec) {
  52. i = EstimateCPUClock();
  53. }
  54. Sort(vec, vec + N_VEC);
  55. return 1.0 / vec[N_VEC / 2];
  56. }
  57. inline double GetSeconds(const STime& a) const {
  58. return static_cast<double>(a) * Freq;
  59. }
  60. inline double GetClockRate() const {
  61. return Rate;
  62. }
  63. inline ui64 GetCyclesPerSecond() const {
  64. return CyclesPerSecond;
  65. }
  66. const double Freq;
  67. const double Rate;
  68. const ui64 CyclesPerSecond;
  69. };
  70. } // namespace
  71. double NHPTimer::GetSeconds(const STime& a) noexcept {
  72. return TFreq::Instance().GetSeconds(a);
  73. }
  74. double NHPTimer::GetClockRate() noexcept {
  75. return TFreq::Instance().GetClockRate();
  76. }
  77. ui64 NHPTimer::GetCyclesPerSecond() noexcept {
  78. return TFreq::Instance().GetCyclesPerSecond();
  79. }
  80. void NHPTimer::GetTime(STime* pTime) noexcept {
  81. *pTime = GetCycleCount();
  82. }
  83. double NHPTimer::GetTimePassed(STime* pTime) noexcept {
  84. STime old(*pTime);
  85. *pTime = GetCycleCount();
  86. return GetSeconds(*pTime - old);
  87. }