]>
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 | #pragma once | |
7 | #include "rocksdb/statistics.h" | |
8 | ||
9 | #include <vector> | |
10 | #include <atomic> | |
11 | #include <string> | |
12 | ||
13 | #include "monitoring/histogram.h" | |
14 | #include "port/likely.h" | |
15 | #include "port/port.h" | |
16 | #include "util/mutexlock.h" | |
17 | #include "util/thread_local.h" | |
18 | ||
19 | namespace rocksdb { | |
20 | ||
21 | enum TickersInternal : uint32_t { | |
22 | INTERNAL_TICKER_ENUM_START = TICKER_ENUM_MAX, | |
23 | INTERNAL_TICKER_ENUM_MAX | |
24 | }; | |
25 | ||
26 | enum HistogramsInternal : uint32_t { | |
27 | INTERNAL_HISTOGRAM_START = HISTOGRAM_ENUM_MAX, | |
28 | INTERNAL_HISTOGRAM_ENUM_MAX | |
29 | }; | |
30 | ||
31 | ||
32 | class StatisticsImpl : public Statistics { | |
33 | public: | |
34 | StatisticsImpl(std::shared_ptr<Statistics> stats, | |
35 | bool enable_internal_stats); | |
36 | virtual ~StatisticsImpl(); | |
37 | ||
38 | virtual uint64_t getTickerCount(uint32_t ticker_type) const override; | |
39 | virtual void histogramData(uint32_t histogram_type, | |
40 | HistogramData* const data) const override; | |
41 | std::string getHistogramString(uint32_t histogram_type) const override; | |
42 | ||
43 | virtual void setTickerCount(uint32_t ticker_type, uint64_t count) override; | |
44 | virtual uint64_t getAndResetTickerCount(uint32_t ticker_type) override; | |
45 | virtual void recordTick(uint32_t ticker_type, uint64_t count) override; | |
46 | virtual void measureTime(uint32_t histogram_type, uint64_t value) override; | |
47 | ||
48 | virtual Status Reset() override; | |
49 | virtual std::string ToString() const override; | |
50 | virtual bool HistEnabledForType(uint32_t type) const override; | |
51 | ||
52 | private: | |
53 | std::shared_ptr<Statistics> stats_shared_; | |
54 | Statistics* stats_; | |
55 | bool enable_internal_stats_; | |
56 | // Synchronizes anything that operates on other threads' thread-specific data | |
57 | // such that operations like Reset() can be performed atomically. | |
58 | mutable port::Mutex aggregate_lock_; | |
59 | ||
60 | // Holds data maintained by each thread for implementing tickers. | |
61 | struct ThreadTickerInfo { | |
62 | std::atomic_uint_fast64_t value; | |
63 | // During teardown, value will be summed into *merged_sum. | |
64 | std::atomic_uint_fast64_t* merged_sum; | |
65 | ||
66 | ThreadTickerInfo(uint_fast64_t _value, | |
67 | std::atomic_uint_fast64_t* _merged_sum) | |
68 | : value(_value), merged_sum(_merged_sum) {} | |
69 | }; | |
70 | ||
71 | // Holds data maintained by each thread for implementing histograms. | |
72 | struct ThreadHistogramInfo { | |
73 | HistogramImpl value; | |
74 | // During teardown, value will be merged into *merged_hist while holding | |
75 | // *merge_lock, which also syncs with the merges necessary for reads. | |
76 | HistogramImpl* merged_hist; | |
77 | port::Mutex* merge_lock; | |
78 | ||
79 | ThreadHistogramInfo(HistogramImpl* _merged_hist, port::Mutex* _merge_lock) | |
80 | : value(), merged_hist(_merged_hist), merge_lock(_merge_lock) {} | |
81 | }; | |
82 | ||
83 | // Holds global data for implementing tickers. | |
84 | struct TickerInfo { | |
85 | TickerInfo() | |
86 | : thread_value(new ThreadLocalPtr(&mergeThreadValue)), merged_sum(0) {} | |
87 | // Holds thread-specific pointer to ThreadTickerInfo | |
88 | std::unique_ptr<ThreadLocalPtr> thread_value; | |
89 | // Sum of thread-specific values for tickers that have been reset due to | |
90 | // thread termination or ThreadLocalPtr destruction. Also, this is used by | |
91 | // setTickerCount() to conveniently change the global value by setting this | |
92 | // while simultaneously zeroing all thread-local values. | |
93 | std::atomic_uint_fast64_t merged_sum; | |
94 | ||
95 | static void mergeThreadValue(void* ptr) { | |
96 | auto info_ptr = static_cast<ThreadTickerInfo*>(ptr); | |
97 | *info_ptr->merged_sum += info_ptr->value; | |
98 | delete info_ptr; | |
99 | } | |
100 | }; | |
101 | ||
102 | // Holds global data for implementing histograms. | |
103 | struct HistogramInfo { | |
104 | HistogramInfo() | |
105 | : merged_hist(), | |
106 | merge_lock(), | |
107 | thread_value(new ThreadLocalPtr(&mergeThreadValue)) {} | |
108 | // Merged thread-specific values for histograms that have been reset due to | |
109 | // thread termination or ThreadLocalPtr destruction. Note these must be | |
110 | // destroyed after thread_value since its destructor accesses them. | |
111 | HistogramImpl merged_hist; | |
112 | mutable port::Mutex merge_lock; | |
113 | // Holds thread-specific pointer to ThreadHistogramInfo | |
114 | std::unique_ptr<ThreadLocalPtr> thread_value; | |
115 | ||
116 | static void mergeThreadValue(void* ptr) { | |
117 | auto info_ptr = static_cast<ThreadHistogramInfo*>(ptr); | |
118 | { | |
119 | MutexLock lock(info_ptr->merge_lock); | |
120 | info_ptr->merged_hist->Merge(info_ptr->value); | |
121 | } | |
122 | delete info_ptr; | |
123 | } | |
124 | ||
125 | // Returns a histogram that merges all histograms (thread-specific and | |
126 | // previously merged ones). | |
127 | std::unique_ptr<HistogramImpl> getMergedHistogram() const; | |
128 | }; | |
129 | ||
130 | uint64_t getTickerCountLocked(uint32_t ticker_type) const; | |
131 | void histogramDataLocked(uint32_t histogram_type, | |
132 | HistogramData* const data) const; | |
133 | void setTickerCountLocked(uint32_t ticker_type, uint64_t count); | |
134 | ||
135 | // Returns the info for this tickerType/thread. It sets a new info with zeroed | |
136 | // counter if none exists. | |
137 | ThreadTickerInfo* getThreadTickerInfo(uint32_t ticker_type); | |
138 | // Returns the info for this histogramType/thread. It sets a new histogram | |
139 | // with zeroed data if none exists. | |
140 | ThreadHistogramInfo* getThreadHistogramInfo(uint32_t histogram_type); | |
141 | ||
142 | TickerInfo tickers_[INTERNAL_TICKER_ENUM_MAX]; | |
143 | HistogramInfo histograms_[INTERNAL_HISTOGRAM_ENUM_MAX]; | |
144 | }; | |
145 | ||
146 | // Utility functions | |
147 | inline void MeasureTime(Statistics* statistics, uint32_t histogram_type, | |
148 | uint64_t value) { | |
149 | if (statistics) { | |
150 | statistics->measureTime(histogram_type, value); | |
151 | } | |
152 | } | |
153 | ||
154 | inline void RecordTick(Statistics* statistics, uint32_t ticker_type, | |
155 | uint64_t count = 1) { | |
156 | if (statistics) { | |
157 | statistics->recordTick(ticker_type, count); | |
158 | } | |
159 | } | |
160 | ||
161 | inline void SetTickerCount(Statistics* statistics, uint32_t ticker_type, | |
162 | uint64_t count) { | |
163 | if (statistics) { | |
164 | statistics->setTickerCount(ticker_type, count); | |
165 | } | |
166 | } | |
167 | ||
168 | } |