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.
6 #include "monitoring/statistics.h"
8 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
13 #include "rocksdb/statistics.h"
14 #include "port/likely.h"
20 std::shared_ptr
<Statistics
> CreateDBStatistics() {
21 return std::make_shared
<StatisticsImpl
>(nullptr, false);
24 StatisticsImpl::StatisticsImpl(
25 std::shared_ptr
<Statistics
> stats
,
26 bool enable_internal_stats
)
27 : stats_shared_(stats
),
29 enable_internal_stats_(enable_internal_stats
) {
32 StatisticsImpl::~StatisticsImpl() {}
34 uint64_t StatisticsImpl::getTickerCount(uint32_t tickerType
) const {
35 MutexLock
lock(&aggregate_lock_
);
36 return getTickerCountLocked(tickerType
);
39 uint64_t StatisticsImpl::getTickerCountLocked(uint32_t tickerType
) const {
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
);
52 return thread_local_sum
+
53 tickers_
[tickerType
].merged_sum
.load(std::memory_order_relaxed
);
56 std::unique_ptr
<HistogramImpl
>
57 StatisticsImpl::HistogramInfo::getMergedHistogram() const {
58 std::unique_ptr
<HistogramImpl
> res_hist(new HistogramImpl());
60 MutexLock
lock(&merge_lock
);
61 res_hist
->Merge(merged_hist
);
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
);
73 void StatisticsImpl::histogramData(uint32_t histogramType
,
74 HistogramData
* const data
) const {
75 MutexLock
lock(&aggregate_lock_
);
76 histogramDataLocked(histogramType
, data
);
79 void StatisticsImpl::histogramDataLocked(uint32_t histogramType
,
80 HistogramData
* const data
) const {
82 enable_internal_stats_
?
83 histogramType
< INTERNAL_HISTOGRAM_ENUM_MAX
:
84 histogramType
< HISTOGRAM_ENUM_MAX
);
85 histograms_
[histogramType
].getMergedHistogram()->Data(data
);
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();
95 StatisticsImpl::ThreadTickerInfo
* StatisticsImpl::getThreadTickerInfo(
96 uint32_t tickerType
) {
98 static_cast<ThreadTickerInfo
*>(tickers_
[tickerType
].thread_value
->Get());
99 if (info_ptr
== nullptr) {
101 new ThreadTickerInfo(0 /* value */, &tickers_
[tickerType
].merged_sum
);
102 tickers_
[tickerType
].thread_value
->Reset(info_ptr
);
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
);
119 void StatisticsImpl::setTickerCount(uint32_t tickerType
, uint64_t count
) {
121 MutexLock
lock(&aggregate_lock_
);
122 setTickerCountLocked(tickerType
, count
);
124 if (stats_
&& tickerType
< TICKER_ENUM_MAX
) {
125 stats_
->setTickerCount(tickerType
, count
);
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
);
139 tickers_
[tickerType
].merged_sum
.store(count
, std::memory_order_relaxed
);
143 uint64_t StatisticsImpl::getAndResetTickerCount(uint32_t tickerType
) {
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
);
157 sum
+= tickers_
[tickerType
].merged_sum
.exchange(
158 0, std::memory_order_relaxed
);
161 if (stats_
&& tickerType
< TICKER_ENUM_MAX
) {
162 stats_
->setTickerCount(tickerType
, 0);
167 void StatisticsImpl::recordTick(uint32_t tickerType
, uint64_t count
) {
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
);
176 if (stats_
&& tickerType
< TICKER_ENUM_MAX
) {
177 stats_
->recordTick(tickerType
, count
);
181 void StatisticsImpl::measureTime(uint32_t histogramType
, uint64_t value
) {
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
);
189 if (stats_
&& histogramType
< HISTOGRAM_ENUM_MAX
) {
190 stats_
->measureTime(histogramType
, value
);
194 Status
StatisticsImpl::Reset() {
195 MutexLock
lock(&aggregate_lock_
);
196 for (uint32_t i
= 0; i
< TICKER_ENUM_MAX
; ++i
) {
197 setTickerCountLocked(i
, 0);
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();
211 // a buffer size used for temp string buffers
212 const int kTmpStrBufferSize
= 200;
216 std::string
StatisticsImpl::ToString() const {
217 MutexLock
lock(&aggregate_lock_
);
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
));
228 for (const auto& h
: HistogramsNameMap
) {
229 if (h
.first
< HISTOGRAM_ENUM_MAX
|| enable_internal_stats_
) {
230 char buffer
[kTmpStrBufferSize
];
232 histogramDataLocked(h
.first
, &hData
);
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
);
245 bool StatisticsImpl::HistEnabledForType(uint32_t type
) const {
246 if (LIKELY(!enable_internal_stats_
)) {
247 return type
< HISTOGRAM_ENUM_MAX
;
252 } // namespace rocksdb