/src/rocksdb/util/stop_watch.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // |
6 | | #pragma once |
7 | | #include "monitoring/statistics_impl.h" |
8 | | #include "rocksdb/system_clock.h" |
9 | | |
10 | | namespace ROCKSDB_NAMESPACE { |
11 | | // Auto-scoped. |
12 | | // When statistics is not nullptr, records the measured time into any enabled |
13 | | // histograms supplied to the constructor. A histogram argument may be omitted |
14 | | // by setting it to Histograms::HISTOGRAM_ENUM_MAX. It is also saved into |
15 | | // *elapsed if the pointer is not nullptr and overwrite is true, it will be |
16 | | // added to *elapsed if overwrite is false. |
17 | | class StopWatch { |
18 | | public: |
19 | | StopWatch(SystemClock* clock, Statistics* statistics, |
20 | | const uint32_t hist_type_1, |
21 | | const uint32_t hist_type_2 = Histograms::HISTOGRAM_ENUM_MAX, |
22 | | uint64_t* elapsed = nullptr, bool overwrite = true, |
23 | | bool delay_enabled = false) |
24 | | : clock_(clock), |
25 | | statistics_(statistics), |
26 | | hist_type_1_(statistics && statistics->HistEnabledForType(hist_type_1) |
27 | | ? hist_type_1 |
28 | | : Histograms::HISTOGRAM_ENUM_MAX), |
29 | | hist_type_2_(statistics && statistics->HistEnabledForType(hist_type_2) |
30 | | ? hist_type_2 |
31 | | : Histograms::HISTOGRAM_ENUM_MAX), |
32 | | elapsed_(elapsed), |
33 | | overwrite_(overwrite), |
34 | | stats_enabled_(statistics && |
35 | | statistics->get_stats_level() > |
36 | | StatsLevel::kExceptTimers && |
37 | | (hist_type_1_ != Histograms::HISTOGRAM_ENUM_MAX || |
38 | | hist_type_2_ != Histograms::HISTOGRAM_ENUM_MAX)), |
39 | | delay_enabled_(delay_enabled), |
40 | | total_delay_(0), |
41 | | delay_start_time_(0), |
42 | | start_time_((stats_enabled_ || elapsed != nullptr) ? clock->NowMicros() |
43 | 5.53M | : 0) {} |
44 | | |
45 | 5.53M | ~StopWatch() { |
46 | 5.53M | if (elapsed_) { |
47 | 0 | if (overwrite_) { |
48 | 0 | *elapsed_ = clock_->NowMicros() - start_time_; |
49 | 0 | } else { |
50 | 0 | *elapsed_ += clock_->NowMicros() - start_time_; |
51 | 0 | } |
52 | 0 | } |
53 | 5.53M | if (elapsed_ && delay_enabled_) { |
54 | 0 | *elapsed_ -= total_delay_; |
55 | 0 | } |
56 | 5.53M | if (stats_enabled_) { |
57 | 0 | const auto time = (elapsed_ != nullptr) |
58 | 0 | ? *elapsed_ |
59 | 0 | : (clock_->NowMicros() - start_time_); |
60 | 0 | if (hist_type_1_ != Histograms::HISTOGRAM_ENUM_MAX) { |
61 | 0 | statistics_->reportTimeToHistogram(hist_type_1_, time); |
62 | 0 | } |
63 | 0 | if (hist_type_2_ != Histograms::HISTOGRAM_ENUM_MAX) { |
64 | 0 | statistics_->reportTimeToHistogram(hist_type_2_, time); |
65 | 0 | } |
66 | 0 | } |
67 | 5.53M | } |
68 | | |
69 | 0 | void DelayStart() { |
70 | | // if delay_start_time_ is not 0, it means we are already tracking delay, |
71 | | // so delay_start_time_ should not be overwritten |
72 | 0 | if (elapsed_ && delay_enabled_ && delay_start_time_ == 0) { |
73 | 0 | delay_start_time_ = clock_->NowMicros(); |
74 | 0 | } |
75 | 0 | } |
76 | | |
77 | 0 | void DelayStop() { |
78 | 0 | if (elapsed_ && delay_enabled_ && delay_start_time_ != 0) { |
79 | 0 | total_delay_ += clock_->NowMicros() - delay_start_time_; |
80 | 0 | } |
81 | | // reset to 0 means currently no delay is being tracked, so two consecutive |
82 | | // calls to DelayStop will not increase total_delay_ |
83 | 0 | delay_start_time_ = 0; |
84 | 0 | } |
85 | | |
86 | 0 | uint64_t GetDelay() const { return delay_enabled_ ? total_delay_ : 0; } |
87 | | |
88 | 0 | uint64_t start_time() const { return start_time_; } |
89 | | |
90 | | private: |
91 | | SystemClock* clock_; |
92 | | Statistics* statistics_; |
93 | | const uint32_t hist_type_1_; |
94 | | const uint32_t hist_type_2_; |
95 | | uint64_t* elapsed_; |
96 | | bool overwrite_; |
97 | | bool stats_enabled_; |
98 | | bool delay_enabled_; |
99 | | uint64_t total_delay_; |
100 | | uint64_t delay_start_time_; |
101 | | const uint64_t start_time_; |
102 | | }; |
103 | | |
104 | | // a nano second precision stopwatch |
105 | | class StopWatchNano { |
106 | | public: |
107 | | explicit StopWatchNano(SystemClock* clock, bool auto_start = false) |
108 | 20.4k | : clock_(clock), start_(0) { |
109 | 20.4k | if (auto_start) { |
110 | 0 | Start(); |
111 | 0 | } |
112 | 20.4k | } |
113 | | |
114 | 0 | void Start() { start_ = clock_->NowNanos(); } |
115 | | |
116 | 0 | uint64_t ElapsedNanos(bool reset = false) { |
117 | 0 | auto now = clock_->NowNanos(); |
118 | 0 | auto elapsed = now - start_; |
119 | 0 | if (reset) { |
120 | 0 | start_ = now; |
121 | 0 | } |
122 | 0 | return elapsed; |
123 | 0 | } |
124 | | |
125 | 0 | uint64_t ElapsedNanosSafe(bool reset = false) { |
126 | 0 | return (clock_ != nullptr) ? ElapsedNanos(reset) : 0U; |
127 | 0 | } |
128 | | |
129 | 12.1k | bool IsStarted() { return start_ != 0; } |
130 | | |
131 | | private: |
132 | | SystemClock* clock_; |
133 | | uint64_t start_; |
134 | | }; |
135 | | |
136 | | } // namespace ROCKSDB_NAMESPACE |