timer.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. #include "metric.h"
  3. #include <util/generic/typetraits.h>
  4. #include <chrono>
  5. namespace NMonitoring {
  6. /**
  7. * A timing scope to record elapsed time since creation.
  8. */
  9. template <typename TMetric,
  10. typename Resolution = std::chrono::milliseconds,
  11. typename Clock = std::chrono::high_resolution_clock>
  12. class TMetricTimerScope {
  13. public:
  14. explicit TMetricTimerScope(TMetric* metric)
  15. : Metric_(metric)
  16. , StartTime_(Clock::now())
  17. {
  18. Y_ENSURE(Metric_);
  19. }
  20. TMetricTimerScope(TMetricTimerScope&) = delete;
  21. TMetricTimerScope& operator=(const TMetricTimerScope&) = delete;
  22. TMetricTimerScope(TMetricTimerScope&& other) {
  23. *this = std::move(other);
  24. }
  25. TMetricTimerScope& operator=(TMetricTimerScope&& other) {
  26. Metric_ = other.Metric_;
  27. other.Metric_ = nullptr;
  28. StartTime_ = std::move(other.StartTime_);
  29. return *this;
  30. }
  31. void Record() {
  32. Y_DEBUG_ABORT_UNLESS(Metric_);
  33. if (Metric_ == nullptr) {
  34. return;
  35. }
  36. auto duration = std::chrono::duration_cast<Resolution>(Clock::now() - StartTime_).count();
  37. if constexpr (std::is_same<TMetric, TGauge>::value) {
  38. Metric_->Set(duration);
  39. } else if constexpr (std::is_same<TMetric, TIntGauge>::value) {
  40. Metric_->Set(duration);
  41. } else if constexpr (std::is_same<TMetric, TCounter>::value) {
  42. Metric_->Add(duration);
  43. } else if constexpr (std::is_same<TMetric, TRate>::value) {
  44. Metric_->Add(duration);
  45. } else if constexpr (std::is_same<TMetric, THistogram>::value) {
  46. Metric_->Record(duration);
  47. } else {
  48. static_assert(TDependentFalse<TMetric>, "Not supported metric type");
  49. }
  50. Metric_ = nullptr;
  51. }
  52. ~TMetricTimerScope() {
  53. if (Metric_ == nullptr) {
  54. return;
  55. }
  56. Record();
  57. }
  58. private:
  59. TMetric* Metric_{nullptr};
  60. typename Clock::time_point StartTime_;
  61. };
  62. /**
  63. * @brief A class that is supposed to use to measure execution time of an asynchronuous operation.
  64. *
  65. * In order to be able to capture an object into a lambda which is then passed to TFuture::Subscribe/Apply,
  66. * the object must be copy constructible (limitation of the std::function class). So, we cannot use the TMetricTimerScope
  67. * with the abovementioned functions without storing it in a shared pointer or somewhere else. This class works around this
  68. * issue with wrapping the timer with a auto_ptr-like hack Also, Record is const so that one doesn't need to make every lambda mutable
  69. * just to record time measurement.
  70. */
  71. template <typename TMetric,
  72. typename Resolution = std::chrono::milliseconds,
  73. typename Clock = std::chrono::high_resolution_clock>
  74. class TFutureFriendlyTimer {
  75. public:
  76. explicit TFutureFriendlyTimer(TMetric* metric)
  77. : Impl_{metric}
  78. {
  79. }
  80. TFutureFriendlyTimer(const TFutureFriendlyTimer& other)
  81. : Impl_{std::move(other.Impl_)}
  82. {
  83. }
  84. TFutureFriendlyTimer& operator=(const TFutureFriendlyTimer& other) {
  85. Impl_ = std::move(other.Impl_);
  86. }
  87. TFutureFriendlyTimer(TFutureFriendlyTimer&&) = default;
  88. TFutureFriendlyTimer& operator=(TFutureFriendlyTimer&& other) = default;
  89. void Record() const {
  90. Impl_.Record();
  91. }
  92. private:
  93. mutable TMetricTimerScope<TMetric, Resolution, Clock> Impl_;
  94. };
  95. template <typename TMetric>
  96. TMetricTimerScope<TMetric> ScopeTimer(TMetric* metric) {
  97. return TMetricTimerScope<TMetric>{metric};
  98. }
  99. template <typename TMetric>
  100. TFutureFriendlyTimer<TMetric> FutureTimer(TMetric* metric) {
  101. return TFutureFriendlyTimer<TMetric>{metric};
  102. }
  103. }