]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | // This source code is licensed under the BSD-style license found in the | |
3 | // LICENSE file in the root directory of this source tree. An additional grant | |
4 | // of patent rights can be found in the PATENTS file in the same directory. | |
5 | // | |
6 | #include "monitoring/statistics.h" | |
7 | ||
8 | #ifndef __STDC_FORMAT_MACROS | |
9 | #define __STDC_FORMAT_MACROS | |
10 | #endif | |
11 | ||
12 | #include <inttypes.h> | |
13 | #include "rocksdb/statistics.h" | |
14 | #include "port/likely.h" | |
15 | #include <algorithm> | |
16 | #include <cstdio> | |
17 | ||
18 | namespace rocksdb { | |
19 | ||
20 | std::shared_ptr<Statistics> CreateDBStatistics() { | |
21 | return std::make_shared<StatisticsImpl>(nullptr, false); | |
22 | } | |
23 | ||
24 | StatisticsImpl::StatisticsImpl( | |
25 | std::shared_ptr<Statistics> stats, | |
26 | bool enable_internal_stats) | |
27 | : stats_shared_(stats), | |
28 | stats_(stats.get()), | |
29 | enable_internal_stats_(enable_internal_stats) { | |
30 | } | |
31 | ||
32 | StatisticsImpl::~StatisticsImpl() {} | |
33 | ||
34 | uint64_t StatisticsImpl::getTickerCount(uint32_t tickerType) const { | |
35 | MutexLock lock(&aggregate_lock_); | |
36 | return getTickerCountLocked(tickerType); | |
37 | } | |
38 | ||
39 | uint64_t StatisticsImpl::getTickerCountLocked(uint32_t tickerType) const { | |
40 | assert( | |
41 | enable_internal_stats_ ? | |
42 | tickerType < INTERNAL_TICKER_ENUM_MAX : | |
43 | tickerType < TICKER_ENUM_MAX); | |
44 | uint64_t thread_local_sum = 0; | |
45 | tickers_[tickerType].thread_value->Fold( | |
46 | [](void* curr_ptr, void* res) { | |
47 | auto* sum_ptr = static_cast<uint64_t*>(res); | |
48 | *sum_ptr += static_cast<std::atomic_uint_fast64_t*>(curr_ptr)->load( | |
49 | std::memory_order_relaxed); | |
50 | }, | |
51 | &thread_local_sum); | |
52 | return thread_local_sum + | |
53 | tickers_[tickerType].merged_sum.load(std::memory_order_relaxed); | |
54 | } | |
55 | ||
56 | std::unique_ptr<HistogramImpl> | |
57 | StatisticsImpl::HistogramInfo::getMergedHistogram() const { | |
58 | std::unique_ptr<HistogramImpl> res_hist(new HistogramImpl()); | |
59 | { | |
60 | MutexLock lock(&merge_lock); | |
61 | res_hist->Merge(merged_hist); | |
62 | } | |
63 | thread_value->Fold( | |
64 | [](void* curr_ptr, void* res) { | |
65 | auto tmp_res_hist = static_cast<HistogramImpl*>(res); | |
66 | auto curr_hist = static_cast<HistogramImpl*>(curr_ptr); | |
67 | tmp_res_hist->Merge(*curr_hist); | |
68 | }, | |
69 | res_hist.get()); | |
70 | return res_hist; | |
71 | } | |
72 | ||
73 | void StatisticsImpl::histogramData(uint32_t histogramType, | |
74 | HistogramData* const data) const { | |
75 | MutexLock lock(&aggregate_lock_); | |
76 | histogramDataLocked(histogramType, data); | |
77 | } | |
78 | ||
79 | void StatisticsImpl::histogramDataLocked(uint32_t histogramType, | |
80 | HistogramData* const data) const { | |
81 | assert( | |
82 | enable_internal_stats_ ? | |
83 | histogramType < INTERNAL_HISTOGRAM_ENUM_MAX : | |
84 | histogramType < HISTOGRAM_ENUM_MAX); | |
85 | histograms_[histogramType].getMergedHistogram()->Data(data); | |
86 | } | |
87 | ||
88 | std::string StatisticsImpl::getHistogramString(uint32_t histogramType) const { | |
89 | MutexLock lock(&aggregate_lock_); | |
90 | assert(enable_internal_stats_ ? histogramType < INTERNAL_HISTOGRAM_ENUM_MAX | |
91 | : histogramType < HISTOGRAM_ENUM_MAX); | |
92 | return histograms_[histogramType].getMergedHistogram()->ToString(); | |
93 | } | |
94 | ||
95 | StatisticsImpl::ThreadTickerInfo* StatisticsImpl::getThreadTickerInfo( | |
96 | uint32_t tickerType) { | |
97 | auto info_ptr = | |
98 | static_cast<ThreadTickerInfo*>(tickers_[tickerType].thread_value->Get()); | |
99 | if (info_ptr == nullptr) { | |
100 | info_ptr = | |
101 | new ThreadTickerInfo(0 /* value */, &tickers_[tickerType].merged_sum); | |
102 | tickers_[tickerType].thread_value->Reset(info_ptr); | |
103 | } | |
104 | return info_ptr; | |
105 | } | |
106 | ||
107 | StatisticsImpl::ThreadHistogramInfo* StatisticsImpl::getThreadHistogramInfo( | |
108 | uint32_t histogram_type) { | |
109 | auto info_ptr = static_cast<ThreadHistogramInfo*>( | |
110 | histograms_[histogram_type].thread_value->Get()); | |
111 | if (info_ptr == nullptr) { | |
112 | info_ptr = new ThreadHistogramInfo(&histograms_[histogram_type].merged_hist, | |
113 | &histograms_[histogram_type].merge_lock); | |
114 | histograms_[histogram_type].thread_value->Reset(info_ptr); | |
115 | } | |
116 | return info_ptr; | |
117 | } | |
118 | ||
119 | void StatisticsImpl::setTickerCount(uint32_t tickerType, uint64_t count) { | |
120 | { | |
121 | MutexLock lock(&aggregate_lock_); | |
122 | setTickerCountLocked(tickerType, count); | |
123 | } | |
124 | if (stats_ && tickerType < TICKER_ENUM_MAX) { | |
125 | stats_->setTickerCount(tickerType, count); | |
126 | } | |
127 | } | |
128 | ||
129 | void StatisticsImpl::setTickerCountLocked(uint32_t tickerType, uint64_t count) { | |
130 | assert(enable_internal_stats_ ? tickerType < INTERNAL_TICKER_ENUM_MAX | |
131 | : tickerType < TICKER_ENUM_MAX); | |
132 | if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) { | |
133 | tickers_[tickerType].thread_value->Fold( | |
134 | [](void* curr_ptr, void* res) { | |
135 | static_cast<std::atomic<uint64_t>*>(curr_ptr)->store( | |
136 | 0, std::memory_order_relaxed); | |
137 | }, | |
138 | nullptr /* res */); | |
139 | tickers_[tickerType].merged_sum.store(count, std::memory_order_relaxed); | |
140 | } | |
141 | } | |
142 | ||
143 | uint64_t StatisticsImpl::getAndResetTickerCount(uint32_t tickerType) { | |
144 | uint64_t sum = 0; | |
145 | { | |
146 | MutexLock lock(&aggregate_lock_); | |
147 | assert(enable_internal_stats_ ? tickerType < INTERNAL_TICKER_ENUM_MAX | |
148 | : tickerType < TICKER_ENUM_MAX); | |
149 | if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) { | |
150 | tickers_[tickerType].thread_value->Fold( | |
151 | [](void* curr_ptr, void* res) { | |
152 | auto* sum_ptr = static_cast<uint64_t*>(res); | |
153 | *sum_ptr += static_cast<std::atomic<uint64_t>*>(curr_ptr)->exchange( | |
154 | 0, std::memory_order_relaxed); | |
155 | }, | |
156 | &sum); | |
157 | sum += tickers_[tickerType].merged_sum.exchange( | |
158 | 0, std::memory_order_relaxed); | |
159 | } | |
160 | } | |
161 | if (stats_ && tickerType < TICKER_ENUM_MAX) { | |
162 | stats_->setTickerCount(tickerType, 0); | |
163 | } | |
164 | return sum; | |
165 | } | |
166 | ||
167 | void StatisticsImpl::recordTick(uint32_t tickerType, uint64_t count) { | |
168 | assert( | |
169 | enable_internal_stats_ ? | |
170 | tickerType < INTERNAL_TICKER_ENUM_MAX : | |
171 | tickerType < TICKER_ENUM_MAX); | |
172 | if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) { | |
173 | auto info_ptr = getThreadTickerInfo(tickerType); | |
174 | info_ptr->value.fetch_add(count, std::memory_order_relaxed); | |
175 | } | |
176 | if (stats_ && tickerType < TICKER_ENUM_MAX) { | |
177 | stats_->recordTick(tickerType, count); | |
178 | } | |
179 | } | |
180 | ||
181 | void StatisticsImpl::measureTime(uint32_t histogramType, uint64_t value) { | |
182 | assert( | |
183 | enable_internal_stats_ ? | |
184 | histogramType < INTERNAL_HISTOGRAM_ENUM_MAX : | |
185 | histogramType < HISTOGRAM_ENUM_MAX); | |
186 | if (histogramType < HISTOGRAM_ENUM_MAX || enable_internal_stats_) { | |
187 | getThreadHistogramInfo(histogramType)->value.Add(value); | |
188 | } | |
189 | if (stats_ && histogramType < HISTOGRAM_ENUM_MAX) { | |
190 | stats_->measureTime(histogramType, value); | |
191 | } | |
192 | } | |
193 | ||
194 | Status StatisticsImpl::Reset() { | |
195 | MutexLock lock(&aggregate_lock_); | |
196 | for (uint32_t i = 0; i < TICKER_ENUM_MAX; ++i) { | |
197 | setTickerCountLocked(i, 0); | |
198 | } | |
199 | for (uint32_t i = 0; i < HISTOGRAM_ENUM_MAX; ++i) { | |
200 | histograms_[i].thread_value->Fold( | |
201 | [](void* curr_ptr, void* res) { | |
202 | static_cast<HistogramImpl*>(curr_ptr)->Clear(); | |
203 | }, | |
204 | nullptr /* res */); | |
205 | } | |
206 | return Status::OK(); | |
207 | } | |
208 | ||
209 | namespace { | |
210 | ||
211 | // a buffer size used for temp string buffers | |
212 | const int kTmpStrBufferSize = 200; | |
213 | ||
214 | } // namespace | |
215 | ||
216 | std::string StatisticsImpl::ToString() const { | |
217 | MutexLock lock(&aggregate_lock_); | |
218 | std::string res; | |
219 | res.reserve(20000); | |
220 | for (const auto& t : TickersNameMap) { | |
221 | if (t.first < TICKER_ENUM_MAX || enable_internal_stats_) { | |
222 | char buffer[kTmpStrBufferSize]; | |
223 | snprintf(buffer, kTmpStrBufferSize, "%s COUNT : %" PRIu64 "\n", | |
224 | t.second.c_str(), getTickerCountLocked(t.first)); | |
225 | res.append(buffer); | |
226 | } | |
227 | } | |
228 | for (const auto& h : HistogramsNameMap) { | |
229 | if (h.first < HISTOGRAM_ENUM_MAX || enable_internal_stats_) { | |
230 | char buffer[kTmpStrBufferSize]; | |
231 | HistogramData hData; | |
232 | histogramDataLocked(h.first, &hData); | |
233 | snprintf( | |
234 | buffer, kTmpStrBufferSize, | |
235 | "%s statistics Percentiles :=> 50 : %f 95 : %f 99 : %f 100 : %f\n", | |
236 | h.second.c_str(), hData.median, hData.percentile95, | |
237 | hData.percentile99, hData.max); | |
238 | res.append(buffer); | |
239 | } | |
240 | } | |
241 | res.shrink_to_fit(); | |
242 | return res; | |
243 | } | |
244 | ||
245 | bool StatisticsImpl::HistEnabledForType(uint32_t type) const { | |
246 | if (LIKELY(!enable_internal_stats_)) { | |
247 | return type < HISTOGRAM_ENUM_MAX; | |
248 | } | |
249 | return true; | |
250 | } | |
251 | ||
252 | } // namespace rocksdb |