/src/rocksdb/monitoring/statistics_impl.h
Line | Count | Source |
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 <atomic> |
8 | | #include <map> |
9 | | #include <string> |
10 | | #include <vector> |
11 | | |
12 | | #include "monitoring/histogram.h" |
13 | | #include "port/likely.h" |
14 | | #include "port/port.h" |
15 | | #include "rocksdb/statistics.h" |
16 | | #include "util/core_local.h" |
17 | | #include "util/mutexlock.h" |
18 | | |
19 | | #ifdef __clang__ |
20 | | #define ROCKSDB_FIELD_UNUSED __attribute__((__unused__)) |
21 | | #else |
22 | | #define ROCKSDB_FIELD_UNUSED |
23 | | #endif // __clang__ |
24 | | |
25 | | #ifndef STRINGIFY |
26 | | #define STRINGIFY(x) #x |
27 | | #define TOSTRING(x) STRINGIFY(x) |
28 | | #endif |
29 | | |
30 | | namespace ROCKSDB_NAMESPACE { |
31 | | |
32 | | enum TickersInternal : uint32_t { |
33 | | INTERNAL_TICKER_ENUM_START = TICKER_ENUM_MAX, |
34 | | INTERNAL_TICKER_ENUM_MAX |
35 | | }; |
36 | | |
37 | | enum HistogramsInternal : uint32_t { |
38 | | INTERNAL_HISTOGRAM_START = HISTOGRAM_ENUM_MAX, |
39 | | INTERNAL_HISTOGRAM_ENUM_MAX |
40 | | }; |
41 | | |
42 | | class StatisticsImpl : public Statistics { |
43 | | public: |
44 | | StatisticsImpl(std::shared_ptr<Statistics> stats); |
45 | | virtual ~StatisticsImpl(); |
46 | 0 | const char* Name() const override { return kClassName(); } |
47 | 0 | static const char* kClassName() { return "BasicStatistics"; } |
48 | | |
49 | | uint64_t getTickerCount(uint32_t ticker_type) const override; |
50 | | void histogramData(uint32_t histogram_type, |
51 | | HistogramData* const data) const override; |
52 | | std::string getHistogramString(uint32_t histogram_type) const override; |
53 | | |
54 | | void setTickerCount(uint32_t ticker_type, uint64_t count) override; |
55 | | uint64_t getAndResetTickerCount(uint32_t ticker_type) override; |
56 | | void recordTick(uint32_t ticker_type, uint64_t count) override; |
57 | | // The function is implemented for now for backward compatibility reason. |
58 | | // In case a user explictly calls it, for example, they may have a wrapped |
59 | | // Statistics object, passing the call to recordTick() into here, nothing |
60 | | // will break. |
61 | 0 | void measureTime(uint32_t histogramType, uint64_t time) override { |
62 | 0 | recordInHistogram(histogramType, time); |
63 | 0 | } |
64 | | void recordInHistogram(uint32_t histogram_type, uint64_t value) override; |
65 | | |
66 | | Status Reset() override; |
67 | | std::string ToString() const override; |
68 | | bool getTickerMap(std::map<std::string, uint64_t>*) const override; |
69 | | bool HistEnabledForType(uint32_t type) const override; |
70 | | |
71 | 0 | const Customizable* Inner() const override { return stats_.get(); } |
72 | | |
73 | | private: |
74 | | // If non-nullptr, forwards updates to the object pointed to by `stats_`. |
75 | | std::shared_ptr<Statistics> stats_; |
76 | | // Synchronizes anything that operates across other cores' local data, |
77 | | // such that operations like Reset() can be performed atomically. |
78 | | mutable port::Mutex aggregate_lock_; |
79 | | |
80 | | // The ticker/histogram data are stored in this structure, which we will store |
81 | | // per-core. It is cache-aligned, so tickers/histograms belonging to different |
82 | | // cores can never share the same cache line. |
83 | | // |
84 | | // Alignment attributes expand to nothing depending on the platform |
85 | | struct ALIGN_AS(CACHE_LINE_SIZE) StatisticsData { |
86 | | std::atomic_uint_fast64_t tickers_[INTERNAL_TICKER_ENUM_MAX] = {{0}}; |
87 | | HistogramImpl histograms_[INTERNAL_HISTOGRAM_ENUM_MAX]; |
88 | | #ifndef HAVE_ALIGNED_NEW |
89 | | char |
90 | | padding[(CACHE_LINE_SIZE - |
91 | | (INTERNAL_TICKER_ENUM_MAX * sizeof(std::atomic_uint_fast64_t) + |
92 | | INTERNAL_HISTOGRAM_ENUM_MAX * sizeof(HistogramImpl)) % |
93 | | CACHE_LINE_SIZE)] ROCKSDB_FIELD_UNUSED; |
94 | | #endif |
95 | 0 | void* operator new(size_t s) { return port::cacheline_aligned_alloc(s); } |
96 | 0 | void* operator new[](size_t s) { return port::cacheline_aligned_alloc(s); } |
97 | 0 | void operator delete(void* p) { port::cacheline_aligned_free(p); } |
98 | 0 | void operator delete[](void* p) { port::cacheline_aligned_free(p); } |
99 | | }; |
100 | | |
101 | | #ifndef TEST_CACHE_LINE_SIZE |
102 | | static_assert(sizeof(StatisticsData) % CACHE_LINE_SIZE == 0, |
103 | | "Expected " TOSTRING(CACHE_LINE_SIZE) "-byte aligned"); |
104 | | #endif |
105 | | |
106 | | CoreLocalArray<StatisticsData> per_core_stats_; |
107 | | |
108 | | uint64_t getTickerCountLocked(uint32_t ticker_type) const; |
109 | | std::unique_ptr<HistogramImpl> getHistogramImplLocked( |
110 | | uint32_t histogram_type) const; |
111 | | void setTickerCountLocked(uint32_t ticker_type, uint64_t count); |
112 | | }; |
113 | | |
114 | | // Utility functions |
115 | | inline void RecordInHistogram(Statistics* statistics, uint32_t histogram_type, |
116 | 980k | uint64_t value) { |
117 | 980k | if (statistics) { |
118 | 0 | statistics->recordInHistogram(histogram_type, value); |
119 | 0 | } |
120 | 980k | } |
121 | | |
122 | | inline void RecordTimeToHistogram(Statistics* statistics, |
123 | 12.4k | uint32_t histogram_type, uint64_t value) { |
124 | 12.4k | if (statistics) { |
125 | 0 | statistics->reportTimeToHistogram(histogram_type, value); |
126 | 0 | } |
127 | 12.4k | } |
128 | | |
129 | | inline void RecordTick(Statistics* statistics, uint32_t ticker_type, |
130 | 6.29M | uint64_t count = 1) { |
131 | 6.29M | if (statistics) { |
132 | 0 | statistics->recordTick(ticker_type, count); |
133 | 0 | } |
134 | 6.29M | } |
135 | | |
136 | | inline void SetTickerCount(Statistics* statistics, uint32_t ticker_type, |
137 | 0 | uint64_t count) { |
138 | 0 | if (statistics) { |
139 | 0 | statistics->setTickerCount(ticker_type, count); |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | } // namespace ROCKSDB_NAMESPACE |