/src/rocksdb/db/internal_stats.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 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
7 | | // Use of this source code is governed by a BSD-style license that can be |
8 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
9 | | // |
10 | | |
11 | | #pragma once |
12 | | |
13 | | #include <map> |
14 | | #include <memory> |
15 | | #include <string> |
16 | | #include <vector> |
17 | | |
18 | | #include "cache/cache_entry_roles.h" |
19 | | #include "db/version_set.h" |
20 | | #include "rocksdb/system_clock.h" |
21 | | #include "util/hash_containers.h" |
22 | | |
23 | | namespace ROCKSDB_NAMESPACE { |
24 | | |
25 | | template <class Stats> |
26 | | class CacheEntryStatsCollector; |
27 | | class DBImpl; |
28 | | class MemTableList; |
29 | | |
30 | | // Config for retrieving a property's value. |
31 | | struct DBPropertyInfo { |
32 | | bool need_out_of_mutex; |
33 | | |
34 | | // gcc had an internal error for initializing union of pointer-to-member- |
35 | | // functions. Workaround is to populate exactly one of the following function |
36 | | // pointers with a non-nullptr value. |
37 | | |
38 | | // @param value Value-result argument for storing the property's string value |
39 | | // @param suffix Argument portion of the property. For example, suffix would |
40 | | // be "5" for the property "rocksdb.num-files-at-level5". So far, only |
41 | | // certain string properties take an argument. |
42 | | bool (InternalStats::*handle_string)(std::string* value, Slice suffix); |
43 | | |
44 | | // @param value Value-result argument for storing the property's uint64 value |
45 | | // @param db Many of the int properties rely on DBImpl methods. |
46 | | // @param version Version is needed in case the property is retrieved without |
47 | | // holding db mutex, which is only supported for int properties. |
48 | | bool (InternalStats::*handle_int)(uint64_t* value, DBImpl* db, |
49 | | Version* version); |
50 | | |
51 | | // @param props Map of general properties to populate |
52 | | // @param suffix Argument portion of the property. (see handle_string) |
53 | | bool (InternalStats::*handle_map)(std::map<std::string, std::string>* props, |
54 | | Slice suffix); |
55 | | |
56 | | // handle the string type properties rely on DBImpl methods |
57 | | // @param value Value-result argument for storing the property's string value |
58 | | bool (DBImpl::*handle_string_dbimpl)(std::string* value); |
59 | | }; |
60 | | |
61 | | const DBPropertyInfo* GetPropertyInfo(const Slice& property); |
62 | | |
63 | | #undef SCORE |
64 | | enum class LevelStatType { |
65 | | INVALID = 0, |
66 | | NUM_FILES, |
67 | | COMPACTED_FILES, |
68 | | SIZE_BYTES, |
69 | | SCORE, |
70 | | READ_GB, |
71 | | RN_GB, |
72 | | RNP1_GB, |
73 | | WRITE_GB, |
74 | | W_NEW_GB, |
75 | | MOVED_GB, |
76 | | WRITE_AMP, |
77 | | READ_MBPS, |
78 | | WRITE_MBPS, |
79 | | COMP_SEC, |
80 | | COMP_CPU_SEC, |
81 | | COMP_COUNT, |
82 | | AVG_SEC, |
83 | | KEY_IN, |
84 | | KEY_DROP, |
85 | | R_BLOB_GB, |
86 | | W_BLOB_GB, |
87 | | TOTAL // total number of types |
88 | | }; |
89 | | |
90 | | struct LevelStat { |
91 | | // This what will be L?.property_name in the flat map returned to the user |
92 | | std::string property_name; |
93 | | // This will be what we will print in the header in the cli |
94 | | std::string header_name; |
95 | | }; |
96 | | |
97 | | struct DBStatInfo { |
98 | | // This what will be property_name in the flat map returned to the user |
99 | | std::string property_name; |
100 | | }; |
101 | | |
102 | | class InternalStats { |
103 | | public: |
104 | | static const std::map<LevelStatType, LevelStat> compaction_level_stats; |
105 | | |
106 | | enum InternalCFStatsType { |
107 | | MEMTABLE_LIMIT_DELAYS, |
108 | | MEMTABLE_LIMIT_STOPS, |
109 | | L0_FILE_COUNT_LIMIT_DELAYS, |
110 | | L0_FILE_COUNT_LIMIT_STOPS, |
111 | | PENDING_COMPACTION_BYTES_LIMIT_DELAYS, |
112 | | PENDING_COMPACTION_BYTES_LIMIT_STOPS, |
113 | | // Write slowdown caused by l0 file count limit while there is ongoing L0 |
114 | | // compaction |
115 | | L0_FILE_COUNT_LIMIT_DELAYS_WITH_ONGOING_COMPACTION, |
116 | | // Write stop caused by l0 file count limit while there is ongoing L0 |
117 | | // compaction |
118 | | L0_FILE_COUNT_LIMIT_STOPS_WITH_ONGOING_COMPACTION, |
119 | | WRITE_STALLS_ENUM_MAX, |
120 | | // End of all write stall stats |
121 | | BYTES_FLUSHED, |
122 | | BYTES_INGESTED_ADD_FILE, |
123 | | INGESTED_NUM_FILES_TOTAL, |
124 | | INGESTED_LEVEL0_NUM_FILES_TOTAL, |
125 | | INGESTED_NUM_KEYS_TOTAL, |
126 | | INTERNAL_CF_STATS_ENUM_MAX, |
127 | | }; |
128 | | |
129 | | enum InternalDBStatsType { |
130 | | kIntStatsWalFileBytes, |
131 | | kIntStatsWalFileSynced, |
132 | | kIntStatsBytesWritten, |
133 | | kIntStatsNumKeysWritten, |
134 | | kIntStatsWriteDoneByOther, |
135 | | kIntStatsWriteDoneBySelf, |
136 | | kIntStatsWriteWithWal, |
137 | | // TODO(hx235): Currently `kIntStatsWriteStallMicros` only measures |
138 | | // "delayed" time of CF-scope write stalls, not including the "stopped" time |
139 | | // nor any DB-scope write stalls (e.g, ones triggered by |
140 | | // `WriteBufferManager`). |
141 | | // |
142 | | // However, the word "write stall" includes both "delayed" and "stopped" |
143 | | // (see `WriteStallCondition`) and DB-scope writes stalls (see |
144 | | // `WriteStallCause`). |
145 | | // |
146 | | // So we should improve, rename or clarify it |
147 | | kIntStatsWriteStallMicros, |
148 | | kIntStatsWriteBufferManagerLimitStopsCounts, |
149 | | kIntStatsNumMax, |
150 | | }; |
151 | | |
152 | | static const std::map<InternalDBStatsType, DBStatInfo> db_stats_type_to_info; |
153 | | |
154 | | InternalStats(int num_levels, SystemClock* clock, ColumnFamilyData* cfd); |
155 | | |
156 | | // Per level compaction stats |
157 | | struct CompactionOutputsStats { |
158 | | uint64_t num_output_records = 0; |
159 | | uint64_t bytes_written = 0; |
160 | | uint64_t bytes_written_blob = 0; |
161 | | uint64_t num_output_files = 0; |
162 | | uint64_t num_output_files_blob = 0; |
163 | | |
164 | 0 | void Add(const CompactionOutputsStats& stats) { |
165 | 0 | this->num_output_records += stats.num_output_records; |
166 | 0 | this->bytes_written += stats.bytes_written; |
167 | 0 | this->bytes_written_blob += stats.bytes_written_blob; |
168 | 0 | this->num_output_files += stats.num_output_files; |
169 | 0 | this->num_output_files_blob += stats.num_output_files_blob; |
170 | 0 | } |
171 | | }; |
172 | | |
173 | | // Per level compaction stats. comp_stats_[level] stores the stats for |
174 | | // compactions that produced data for the specified "level". |
175 | | struct CompactionStats { |
176 | | uint64_t micros; |
177 | | uint64_t cpu_micros; |
178 | | |
179 | | // The number of bytes read from all non-output levels (table files) |
180 | | uint64_t bytes_read_non_output_levels; |
181 | | |
182 | | // The number of bytes read from the compaction output level (table files) |
183 | | uint64_t bytes_read_output_level; |
184 | | |
185 | | // The number of bytes read from blob files |
186 | | uint64_t bytes_read_blob; |
187 | | |
188 | | // Total number of bytes written to table files during compaction |
189 | | uint64_t bytes_written; |
190 | | |
191 | | // Total number of bytes written to blob files during compaction |
192 | | uint64_t bytes_written_blob; |
193 | | |
194 | | // Total number of bytes moved to the output level (table files) |
195 | | uint64_t bytes_moved; |
196 | | |
197 | | // The number of compaction input files in all non-output levels (table |
198 | | // files) |
199 | | int num_input_files_in_non_output_levels; |
200 | | |
201 | | // The number of compaction input files in the output level (table files) |
202 | | int num_input_files_in_output_level; |
203 | | |
204 | | // The number of compaction output files (table files) |
205 | | int num_output_files; |
206 | | |
207 | | // The number of compaction output files (blob files) |
208 | | int num_output_files_blob; |
209 | | |
210 | | // Total incoming entries during compaction between levels N and N+1 |
211 | | uint64_t num_input_records; |
212 | | |
213 | | // Accumulated diff number of entries |
214 | | // (num input entries - num output entries) for compaction levels N and N+1 |
215 | | uint64_t num_dropped_records; |
216 | | |
217 | | // Total output entries from compaction |
218 | | uint64_t num_output_records; |
219 | | |
220 | | // Number of compactions done |
221 | | int count; |
222 | | |
223 | | // Number of compactions done per CompactionReason |
224 | | int counts[static_cast<int>(CompactionReason::kNumOfReasons)]{}; |
225 | | |
226 | | explicit CompactionStats() |
227 | | : micros(0), |
228 | | cpu_micros(0), |
229 | | bytes_read_non_output_levels(0), |
230 | | bytes_read_output_level(0), |
231 | | bytes_read_blob(0), |
232 | | bytes_written(0), |
233 | | bytes_written_blob(0), |
234 | | bytes_moved(0), |
235 | | num_input_files_in_non_output_levels(0), |
236 | | num_input_files_in_output_level(0), |
237 | | num_output_files(0), |
238 | | num_output_files_blob(0), |
239 | | num_input_records(0), |
240 | | num_dropped_records(0), |
241 | | num_output_records(0), |
242 | 505k | count(0) { |
243 | 505k | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
244 | 10.6M | for (int i = 0; i < num_of_reasons; i++) { |
245 | 10.1M | counts[i] = 0; |
246 | 10.1M | } |
247 | 505k | } |
248 | | |
249 | | explicit CompactionStats(CompactionReason reason, int c) |
250 | | : micros(0), |
251 | | cpu_micros(0), |
252 | | bytes_read_non_output_levels(0), |
253 | | bytes_read_output_level(0), |
254 | | bytes_read_blob(0), |
255 | | bytes_written(0), |
256 | | bytes_written_blob(0), |
257 | | bytes_moved(0), |
258 | | num_input_files_in_non_output_levels(0), |
259 | | num_input_files_in_output_level(0), |
260 | | num_output_files(0), |
261 | | num_output_files_blob(0), |
262 | | num_input_records(0), |
263 | | num_dropped_records(0), |
264 | | num_output_records(0), |
265 | 13.8k | count(c) { |
266 | 13.8k | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
267 | 289k | for (int i = 0; i < num_of_reasons; i++) { |
268 | 276k | counts[i] = 0; |
269 | 276k | } |
270 | 13.8k | int r = static_cast<int>(reason); |
271 | 13.8k | if (r >= 0 && r < num_of_reasons) { |
272 | 13.8k | counts[r] = c; |
273 | 13.8k | } else { |
274 | 0 | count = 0; |
275 | 0 | } |
276 | 13.8k | } |
277 | | |
278 | | CompactionStats(const CompactionStats& c) |
279 | | : micros(c.micros), |
280 | | cpu_micros(c.cpu_micros), |
281 | | bytes_read_non_output_levels(c.bytes_read_non_output_levels), |
282 | | bytes_read_output_level(c.bytes_read_output_level), |
283 | | bytes_read_blob(c.bytes_read_blob), |
284 | | bytes_written(c.bytes_written), |
285 | | bytes_written_blob(c.bytes_written_blob), |
286 | | bytes_moved(c.bytes_moved), |
287 | | num_input_files_in_non_output_levels( |
288 | | c.num_input_files_in_non_output_levels), |
289 | | num_input_files_in_output_level(c.num_input_files_in_output_level), |
290 | | num_output_files(c.num_output_files), |
291 | | num_output_files_blob(c.num_output_files_blob), |
292 | | num_input_records(c.num_input_records), |
293 | | num_dropped_records(c.num_dropped_records), |
294 | | num_output_records(c.num_output_records), |
295 | 134 | count(c.count) { |
296 | 134 | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
297 | 2.81k | for (int i = 0; i < num_of_reasons; i++) { |
298 | 2.68k | counts[i] = c.counts[i]; |
299 | 2.68k | } |
300 | 134 | } |
301 | | |
302 | 134 | CompactionStats& operator=(const CompactionStats& c) { |
303 | 134 | micros = c.micros; |
304 | 134 | cpu_micros = c.cpu_micros; |
305 | 134 | bytes_read_non_output_levels = c.bytes_read_non_output_levels; |
306 | 134 | bytes_read_output_level = c.bytes_read_output_level; |
307 | 134 | bytes_read_blob = c.bytes_read_blob; |
308 | 134 | bytes_written = c.bytes_written; |
309 | 134 | bytes_written_blob = c.bytes_written_blob; |
310 | 134 | bytes_moved = c.bytes_moved; |
311 | 134 | num_input_files_in_non_output_levels = |
312 | 134 | c.num_input_files_in_non_output_levels; |
313 | 134 | num_input_files_in_output_level = c.num_input_files_in_output_level; |
314 | 134 | num_output_files = c.num_output_files; |
315 | 134 | num_output_files_blob = c.num_output_files_blob; |
316 | 134 | num_input_records = c.num_input_records; |
317 | 134 | num_dropped_records = c.num_dropped_records; |
318 | 134 | num_output_records = c.num_output_records; |
319 | 134 | count = c.count; |
320 | | |
321 | 134 | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
322 | 2.81k | for (int i = 0; i < num_of_reasons; i++) { |
323 | 2.68k | counts[i] = c.counts[i]; |
324 | 2.68k | } |
325 | 134 | return *this; |
326 | 134 | } |
327 | | |
328 | 0 | void Clear() { |
329 | 0 | this->micros = 0; |
330 | 0 | this->cpu_micros = 0; |
331 | 0 | this->bytes_read_non_output_levels = 0; |
332 | 0 | this->bytes_read_output_level = 0; |
333 | 0 | this->bytes_read_blob = 0; |
334 | 0 | this->bytes_written = 0; |
335 | 0 | this->bytes_written_blob = 0; |
336 | 0 | this->bytes_moved = 0; |
337 | 0 | this->num_input_files_in_non_output_levels = 0; |
338 | 0 | this->num_input_files_in_output_level = 0; |
339 | 0 | this->num_output_files = 0; |
340 | 0 | this->num_output_files_blob = 0; |
341 | 0 | this->num_input_records = 0; |
342 | 0 | this->num_dropped_records = 0; |
343 | 0 | this->num_output_records = 0; |
344 | 0 | this->count = 0; |
345 | 0 | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
346 | 0 | for (int i = 0; i < num_of_reasons; i++) { |
347 | 0 | counts[i] = 0; |
348 | 0 | } |
349 | 0 | } |
350 | | |
351 | 23.3k | void Add(const CompactionStats& c) { |
352 | 23.3k | this->micros += c.micros; |
353 | 23.3k | this->cpu_micros += c.cpu_micros; |
354 | 23.3k | this->bytes_read_non_output_levels += c.bytes_read_non_output_levels; |
355 | 23.3k | this->bytes_read_output_level += c.bytes_read_output_level; |
356 | 23.3k | this->bytes_read_blob += c.bytes_read_blob; |
357 | 23.3k | this->bytes_written += c.bytes_written; |
358 | 23.3k | this->bytes_written_blob += c.bytes_written_blob; |
359 | 23.3k | this->bytes_moved += c.bytes_moved; |
360 | 23.3k | this->num_input_files_in_non_output_levels += |
361 | 23.3k | c.num_input_files_in_non_output_levels; |
362 | 23.3k | this->num_input_files_in_output_level += |
363 | 23.3k | c.num_input_files_in_output_level; |
364 | 23.3k | this->num_output_files += c.num_output_files; |
365 | 23.3k | this->num_output_files_blob += c.num_output_files_blob; |
366 | 23.3k | this->num_input_records += c.num_input_records; |
367 | 23.3k | this->num_dropped_records += c.num_dropped_records; |
368 | 23.3k | this->num_output_records += c.num_output_records; |
369 | 23.3k | this->count += c.count; |
370 | 23.3k | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
371 | 489k | for (int i = 0; i < num_of_reasons; i++) { |
372 | 466k | counts[i] += c.counts[i]; |
373 | 466k | } |
374 | 23.3k | } |
375 | | |
376 | 2.16k | void Add(const CompactionOutputsStats& stats) { |
377 | 2.16k | this->num_output_files += static_cast<int>(stats.num_output_files); |
378 | 2.16k | this->num_output_records += stats.num_output_records; |
379 | 2.16k | this->bytes_written += stats.bytes_written; |
380 | 2.16k | this->bytes_written_blob += stats.bytes_written_blob; |
381 | 2.16k | this->num_output_files_blob += |
382 | 2.16k | static_cast<int>(stats.num_output_files_blob); |
383 | 2.16k | } |
384 | | |
385 | 134 | void Subtract(const CompactionStats& c) { |
386 | 134 | this->micros -= c.micros; |
387 | 134 | this->cpu_micros -= c.cpu_micros; |
388 | 134 | this->bytes_read_non_output_levels -= c.bytes_read_non_output_levels; |
389 | 134 | this->bytes_read_output_level -= c.bytes_read_output_level; |
390 | 134 | this->bytes_read_blob -= c.bytes_read_blob; |
391 | 134 | this->bytes_written -= c.bytes_written; |
392 | 134 | this->bytes_written_blob -= c.bytes_written_blob; |
393 | 134 | this->bytes_moved -= c.bytes_moved; |
394 | 134 | this->num_input_files_in_non_output_levels -= |
395 | 134 | c.num_input_files_in_non_output_levels; |
396 | 134 | this->num_input_files_in_output_level -= |
397 | 134 | c.num_input_files_in_output_level; |
398 | 134 | this->num_output_files -= c.num_output_files; |
399 | 134 | this->num_output_files_blob -= c.num_output_files_blob; |
400 | 134 | this->num_input_records -= c.num_input_records; |
401 | 134 | this->num_dropped_records -= c.num_dropped_records; |
402 | 134 | this->num_output_records -= c.num_output_records; |
403 | 134 | this->count -= c.count; |
404 | 134 | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
405 | 2.81k | for (int i = 0; i < num_of_reasons; i++) { |
406 | 2.68k | counts[i] -= c.counts[i]; |
407 | 2.68k | } |
408 | 134 | } |
409 | | |
410 | 0 | void ResetCompactionReason(CompactionReason reason) { |
411 | 0 | int num_of_reasons = static_cast<int>(CompactionReason::kNumOfReasons); |
412 | 0 | assert(count == 1); // only support update one compaction reason |
413 | 0 | for (int i = 0; i < num_of_reasons; i++) { |
414 | 0 | counts[i] = 0; |
415 | 0 | } |
416 | 0 | int r = static_cast<int>(reason); |
417 | 0 | assert(r >= 0 && r < num_of_reasons); |
418 | 0 | counts[r] = 1; |
419 | 0 | } |
420 | | }; |
421 | | |
422 | | // Compaction stats, for per_key_placement compaction, it includes 2 levels |
423 | | // stats: the last level and the penultimate level. |
424 | | struct CompactionStatsFull { |
425 | | // the stats for the target primary output level |
426 | | CompactionStats stats; |
427 | | |
428 | | // stats for penultimate level output if exist |
429 | | bool has_penultimate_level_output = false; |
430 | | CompactionStats penultimate_level_stats; |
431 | | |
432 | 0 | explicit CompactionStatsFull() : stats(), penultimate_level_stats() {} |
433 | | |
434 | | explicit CompactionStatsFull(CompactionReason reason, int c) |
435 | 2.16k | : stats(reason, c), penultimate_level_stats(reason, c) {} |
436 | | |
437 | 1.45k | uint64_t TotalBytesWritten() const { |
438 | 1.45k | uint64_t bytes_written = stats.bytes_written + stats.bytes_written_blob; |
439 | 1.45k | if (has_penultimate_level_output) { |
440 | 0 | bytes_written += penultimate_level_stats.bytes_written + |
441 | 0 | penultimate_level_stats.bytes_written_blob; |
442 | 0 | } |
443 | 1.45k | return bytes_written; |
444 | 1.45k | } |
445 | | |
446 | 2.16k | uint64_t DroppedRecords() { |
447 | 2.16k | uint64_t output_records = stats.num_output_records; |
448 | 2.16k | if (has_penultimate_level_output) { |
449 | 0 | output_records += penultimate_level_stats.num_output_records; |
450 | 0 | } |
451 | 2.16k | if (stats.num_input_records > output_records) { |
452 | 1.69k | return stats.num_input_records - output_records; |
453 | 1.69k | } |
454 | 475 | return 0; |
455 | 2.16k | } |
456 | | |
457 | 2.16k | void SetMicros(uint64_t val) { |
458 | 2.16k | stats.micros = val; |
459 | 2.16k | penultimate_level_stats.micros = val; |
460 | 2.16k | } |
461 | | |
462 | 2.16k | void AddCpuMicros(uint64_t val) { |
463 | 2.16k | stats.cpu_micros += val; |
464 | 2.16k | penultimate_level_stats.cpu_micros += val; |
465 | 2.16k | } |
466 | | }; |
467 | | |
468 | | // For use with CacheEntryStatsCollector |
469 | | struct CacheEntryRoleStats { |
470 | | uint64_t cache_capacity = 0; |
471 | | uint64_t cache_usage = 0; |
472 | | size_t table_size = 0; |
473 | | size_t occupancy = 0; |
474 | | std::string cache_id; |
475 | | std::array<uint64_t, kNumCacheEntryRoles> total_charges; |
476 | | std::array<size_t, kNumCacheEntryRoles> entry_counts; |
477 | | uint32_t collection_count = 0; |
478 | | uint32_t copies_of_last_collection = 0; |
479 | | uint64_t last_start_time_micros_ = 0; |
480 | | uint64_t last_end_time_micros_ = 0; |
481 | | uint32_t hash_seed = 0; |
482 | | |
483 | 134 | void Clear() { |
484 | | // Wipe everything except collection_count |
485 | 134 | uint32_t saved_collection_count = collection_count; |
486 | 134 | *this = CacheEntryRoleStats(); |
487 | 134 | collection_count = saved_collection_count; |
488 | 134 | } |
489 | | |
490 | | void BeginCollection(Cache*, SystemClock*, uint64_t start_time_micros); |
491 | | std::function<void(const Slice& key, Cache::ObjectPtr value, size_t charge, |
492 | | const Cache::CacheItemHelper* helper)> |
493 | | GetEntryCallback(); |
494 | | void EndCollection(Cache*, SystemClock*, uint64_t end_time_micros); |
495 | | void SkippedCollection(); |
496 | | |
497 | | std::string ToString(SystemClock* clock) const; |
498 | | void ToMap(std::map<std::string, std::string>* values, |
499 | | SystemClock* clock) const; |
500 | | |
501 | | private: |
502 | | uint64_t GetLastDurationMicros() const; |
503 | | }; |
504 | | |
505 | 0 | void Clear() { |
506 | 0 | for (int i = 0; i < kIntStatsNumMax; i++) { |
507 | 0 | db_stats_[i].store(0); |
508 | 0 | } |
509 | 0 | for (int i = 0; i < INTERNAL_CF_STATS_ENUM_MAX; i++) { |
510 | 0 | cf_stats_count_[i] = 0; |
511 | 0 | cf_stats_value_[i] = 0; |
512 | 0 | } |
513 | 0 | for (auto& comp_stat : comp_stats_) { |
514 | 0 | comp_stat.Clear(); |
515 | 0 | } |
516 | 0 | per_key_placement_comp_stats_.Clear(); |
517 | 0 | for (auto& h : file_read_latency_) { |
518 | 0 | h.Clear(); |
519 | 0 | } |
520 | 0 | blob_file_read_latency_.Clear(); |
521 | 0 | cf_stats_snapshot_.Clear(); |
522 | 0 | db_stats_snapshot_.Clear(); |
523 | 0 | bg_error_count_ = 0; |
524 | 0 | started_at_ = clock_->NowMicros(); |
525 | 0 | has_cf_change_since_dump_ = true; |
526 | 0 | } |
527 | | |
528 | | void AddCompactionStats(int level, Env::Priority thread_pri, |
529 | 11.6k | const CompactionStats& stats) { |
530 | 11.6k | comp_stats_[level].Add(stats); |
531 | 11.6k | comp_stats_by_pri_[thread_pri].Add(stats); |
532 | 11.6k | } |
533 | | |
534 | | void AddCompactionStats(int level, Env::Priority thread_pri, |
535 | 2.16k | const CompactionStatsFull& comp_stats_full) { |
536 | 2.16k | AddCompactionStats(level, thread_pri, comp_stats_full.stats); |
537 | 2.16k | if (comp_stats_full.has_penultimate_level_output) { |
538 | 0 | per_key_placement_comp_stats_.Add( |
539 | 0 | comp_stats_full.penultimate_level_stats); |
540 | 0 | } |
541 | 2.16k | } |
542 | | |
543 | 1.21k | void IncBytesMoved(int level, uint64_t amount) { |
544 | 1.21k | comp_stats_[level].bytes_moved += amount; |
545 | 1.21k | } |
546 | | |
547 | 9.47k | void AddCFStats(InternalCFStatsType type, uint64_t value) { |
548 | 9.47k | has_cf_change_since_dump_ = true; |
549 | 9.47k | cf_stats_value_[type] += value; |
550 | 9.47k | ++cf_stats_count_[type]; |
551 | 9.47k | } |
552 | | |
553 | | void AddDBStats(InternalDBStatsType type, uint64_t value, |
554 | 6.91M | bool concurrent = false) { |
555 | 6.91M | auto& v = db_stats_[type]; |
556 | 6.91M | if (concurrent) { |
557 | 0 | v.fetch_add(value, std::memory_order_relaxed); |
558 | 6.91M | } else { |
559 | 6.91M | v.store(v.load(std::memory_order_relaxed) + value, |
560 | 6.91M | std::memory_order_relaxed); |
561 | 6.91M | } |
562 | 6.91M | } |
563 | | |
564 | 792 | uint64_t GetDBStats(InternalDBStatsType type) { |
565 | 792 | return db_stats_[type].load(std::memory_order_relaxed); |
566 | 792 | } |
567 | | |
568 | 65.8k | HistogramImpl* GetFileReadHist(int level) { |
569 | 65.8k | return &file_read_latency_[level]; |
570 | 65.8k | } |
571 | | |
572 | 38.8k | HistogramImpl* GetBlobFileReadHist() { return &blob_file_read_latency_; } |
573 | | |
574 | 0 | uint64_t GetBackgroundErrorCount() const { return bg_error_count_; } |
575 | | |
576 | 0 | uint64_t BumpAndGetBackgroundErrorCount() { return ++bg_error_count_; } |
577 | | |
578 | | bool GetStringProperty(const DBPropertyInfo& property_info, |
579 | | const Slice& property, std::string* value); |
580 | | |
581 | | bool GetMapProperty(const DBPropertyInfo& property_info, |
582 | | const Slice& property, |
583 | | std::map<std::string, std::string>* value); |
584 | | |
585 | | bool GetIntProperty(const DBPropertyInfo& property_info, uint64_t* value, |
586 | | DBImpl* db); |
587 | | |
588 | | bool GetIntPropertyOutOfMutex(const DBPropertyInfo& property_info, |
589 | | Version* version, uint64_t* value); |
590 | | |
591 | | // Unless there is a recent enough collection of the stats, collect and |
592 | | // saved new cache entry stats. If `foreground`, require data to be more |
593 | | // recent to skip re-collection. |
594 | | // |
595 | | // This should only be called while NOT holding the DB mutex. |
596 | | void CollectCacheEntryStats(bool foreground); |
597 | | |
598 | 0 | const uint64_t* TEST_GetCFStatsValue() const { return cf_stats_value_; } |
599 | | |
600 | 0 | const std::vector<CompactionStats>& TEST_GetCompactionStats() const { |
601 | 0 | return comp_stats_; |
602 | 0 | } |
603 | | |
604 | 0 | const CompactionStats& TEST_GetPerKeyPlacementCompactionStats() const { |
605 | 0 | return per_key_placement_comp_stats_; |
606 | 0 | } |
607 | | |
608 | | void TEST_GetCacheEntryRoleStats(CacheEntryRoleStats* stats, bool foreground); |
609 | | |
610 | | // Store a mapping from the user-facing DB::Properties string to our |
611 | | // DBPropertyInfo struct used internally for retrieving properties. |
612 | | static const UnorderedMap<std::string, DBPropertyInfo> ppt_name_to_info; |
613 | | |
614 | | static const std::string kPeriodicCFStats; |
615 | | |
616 | | private: |
617 | | void DumpDBMapStats(std::map<std::string, std::string>* db_stats); |
618 | | void DumpDBStats(std::string* value); |
619 | | |
620 | | void DumpDBMapStatsWriteStall(std::map<std::string, std::string>* value); |
621 | | void DumpDBStatsWriteStall(std::string* value); |
622 | | |
623 | | void DumpCFMapStats(std::map<std::string, std::string>* cf_stats); |
624 | | void DumpCFMapStats( |
625 | | const VersionStorageInfo* vstorage, |
626 | | std::map<int, std::map<LevelStatType, double>>* level_stats, |
627 | | CompactionStats* compaction_stats_sum); |
628 | | void DumpCFMapStatsByPriority( |
629 | | std::map<int, std::map<LevelStatType, double>>* priorities_stats); |
630 | | void DumpCFStats(std::string* value); |
631 | | // if is_periodic = true, it is an internal call by RocksDB periodically to |
632 | | // dump the status. |
633 | | void DumpCFStatsNoFileHistogram(bool is_periodic, std::string* value); |
634 | | // if is_periodic = true, it is an internal call by RocksDB periodically to |
635 | | // dump the status. |
636 | | void DumpCFFileHistogram(std::string* value); |
637 | | |
638 | | void DumpCFMapStatsWriteStall(std::map<std::string, std::string>* value); |
639 | | void DumpCFStatsWriteStall(std::string* value, |
640 | | uint64_t* total_stall_count = nullptr); |
641 | | |
642 | | Cache* GetBlockCacheForStats(); |
643 | | Cache* GetBlobCacheForStats(); |
644 | | |
645 | | // Per-DB stats |
646 | | std::atomic<uint64_t> db_stats_[kIntStatsNumMax]; |
647 | | // Per-ColumnFamily stats |
648 | | uint64_t cf_stats_value_[INTERNAL_CF_STATS_ENUM_MAX]; |
649 | | uint64_t cf_stats_count_[INTERNAL_CF_STATS_ENUM_MAX]; |
650 | | // Initialize/reference the collector in constructor so that we don't need |
651 | | // additional synchronization in InternalStats, relying on synchronization |
652 | | // in CacheEntryStatsCollector::GetStats. This collector is pinned in cache |
653 | | // (through a shared_ptr) so that it does not get immediately ejected from |
654 | | // a full cache, which would force a re-scan on the next GetStats. |
655 | | std::shared_ptr<CacheEntryStatsCollector<CacheEntryRoleStats>> |
656 | | cache_entry_stats_collector_; |
657 | | // Per-ColumnFamily/level compaction stats |
658 | | std::vector<CompactionStats> comp_stats_; |
659 | | std::vector<CompactionStats> comp_stats_by_pri_; |
660 | | CompactionStats per_key_placement_comp_stats_; |
661 | | std::vector<HistogramImpl> file_read_latency_; |
662 | | HistogramImpl blob_file_read_latency_; |
663 | | bool has_cf_change_since_dump_; |
664 | | // How many periods of no change since the last time stats are dumped for |
665 | | // a periodic dump. |
666 | | int no_cf_change_period_since_dump_ = 0; |
667 | | uint64_t last_histogram_num = std::numeric_limits<uint64_t>::max(); |
668 | | static const int kMaxNoChangePeriodSinceDump; |
669 | | |
670 | | // Used to compute per-interval statistics |
671 | | struct CFStatsSnapshot { |
672 | | // ColumnFamily-level stats |
673 | | CompactionStats comp_stats; |
674 | | uint64_t ingest_bytes_flush; // Bytes written to L0 (Flush) |
675 | | uint64_t stall_count; // Total counts of CF-scope write stalls |
676 | | // Stats from compaction jobs - bytes written, bytes read, duration. |
677 | | uint64_t compact_bytes_write; |
678 | | uint64_t compact_bytes_read; |
679 | | uint64_t compact_micros; |
680 | | double seconds_up; |
681 | | |
682 | | // AddFile specific stats |
683 | | uint64_t ingest_bytes_addfile; // Total Bytes ingested |
684 | | uint64_t ingest_files_addfile; // Total number of files ingested |
685 | | uint64_t ingest_l0_files_addfile; // Total number of files ingested to L0 |
686 | | uint64_t ingest_keys_addfile; // Total number of keys ingested |
687 | | |
688 | | CFStatsSnapshot() |
689 | | : ingest_bytes_flush(0), |
690 | | stall_count(0), |
691 | | compact_bytes_write(0), |
692 | | compact_bytes_read(0), |
693 | | compact_micros(0), |
694 | | seconds_up(0), |
695 | | ingest_bytes_addfile(0), |
696 | | ingest_files_addfile(0), |
697 | | ingest_l0_files_addfile(0), |
698 | 38.8k | ingest_keys_addfile(0) {} |
699 | | |
700 | 0 | void Clear() { |
701 | 0 | comp_stats.Clear(); |
702 | 0 | ingest_bytes_flush = 0; |
703 | 0 | stall_count = 0; |
704 | 0 | compact_bytes_write = 0; |
705 | 0 | compact_bytes_read = 0; |
706 | 0 | compact_micros = 0; |
707 | 0 | seconds_up = 0; |
708 | 0 | ingest_bytes_addfile = 0; |
709 | 0 | ingest_files_addfile = 0; |
710 | 0 | ingest_l0_files_addfile = 0; |
711 | 0 | ingest_keys_addfile = 0; |
712 | 0 | } |
713 | | } cf_stats_snapshot_; |
714 | | |
715 | | struct DBStatsSnapshot { |
716 | | // DB-level stats |
717 | | uint64_t ingest_bytes; // Bytes written by user |
718 | | uint64_t wal_bytes; // Bytes written to WAL |
719 | | uint64_t wal_synced; // Number of times WAL is synced |
720 | | uint64_t write_with_wal; // Number of writes that request WAL |
721 | | // These count the number of writes processed by the calling thread or |
722 | | // another thread. |
723 | | uint64_t write_other; |
724 | | uint64_t write_self; |
725 | | // Total number of keys written. write_self and write_other measure number |
726 | | // of write requests written, Each of the write request can contain updates |
727 | | // to multiple keys. num_keys_written is total number of keys updated by all |
728 | | // those writes. |
729 | | uint64_t num_keys_written; |
730 | | // Total time writes delayed by stalls. |
731 | | uint64_t write_stall_micros; |
732 | | double seconds_up; |
733 | | |
734 | | DBStatsSnapshot() |
735 | | : ingest_bytes(0), |
736 | | wal_bytes(0), |
737 | | wal_synced(0), |
738 | | write_with_wal(0), |
739 | | write_other(0), |
740 | | write_self(0), |
741 | | num_keys_written(0), |
742 | | write_stall_micros(0), |
743 | 38.8k | seconds_up(0) {} |
744 | | |
745 | 0 | void Clear() { |
746 | 0 | ingest_bytes = 0; |
747 | 0 | wal_bytes = 0; |
748 | 0 | wal_synced = 0; |
749 | 0 | write_with_wal = 0; |
750 | 0 | write_other = 0; |
751 | 0 | write_self = 0; |
752 | 0 | num_keys_written = 0; |
753 | 0 | write_stall_micros = 0; |
754 | 0 | seconds_up = 0; |
755 | 0 | } |
756 | | } db_stats_snapshot_; |
757 | | |
758 | | // Handler functions for getting property values. They use "value" as a value- |
759 | | // result argument, and return true upon successfully setting "value". |
760 | | bool HandleNumFilesAtLevel(std::string* value, Slice suffix); |
761 | | bool HandleCompressionRatioAtLevelPrefix(std::string* value, Slice suffix); |
762 | | bool HandleLevelStats(std::string* value, Slice suffix); |
763 | | bool HandleStats(std::string* value, Slice suffix); |
764 | | bool HandleCFMapStats(std::map<std::string, std::string>* compaction_stats, |
765 | | Slice suffix); |
766 | | bool HandleCFStats(std::string* value, Slice suffix); |
767 | | bool HandleCFStatsNoFileHistogram(std::string* value, Slice suffix); |
768 | | bool HandleCFFileHistogram(std::string* value, Slice suffix); |
769 | | bool HandleCFStatsPeriodic(std::string* value, Slice suffix); |
770 | | bool HandleCFWriteStallStats(std::string* value, Slice suffix); |
771 | | bool HandleCFWriteStallStatsMap(std::map<std::string, std::string>* values, |
772 | | Slice suffix); |
773 | | bool HandleDBMapStats(std::map<std::string, std::string>* compaction_stats, |
774 | | Slice suffix); |
775 | | bool HandleDBStats(std::string* value, Slice suffix); |
776 | | bool HandleDBWriteStallStats(std::string* value, Slice suffix); |
777 | | bool HandleDBWriteStallStatsMap(std::map<std::string, std::string>* values, |
778 | | Slice suffix); |
779 | | bool HandleSsTables(std::string* value, Slice suffix); |
780 | | bool HandleAggregatedTableProperties(std::string* value, Slice suffix); |
781 | | bool HandleAggregatedTablePropertiesAtLevel(std::string* value, Slice suffix); |
782 | | bool HandleAggregatedTablePropertiesMap( |
783 | | std::map<std::string, std::string>* values, Slice suffix); |
784 | | bool HandleAggregatedTablePropertiesAtLevelMap( |
785 | | std::map<std::string, std::string>* values, Slice suffix); |
786 | | bool HandleNumImmutableMemTable(uint64_t* value, DBImpl* db, |
787 | | Version* version); |
788 | | bool HandleNumImmutableMemTableFlushed(uint64_t* value, DBImpl* db, |
789 | | Version* version); |
790 | | bool HandleMemTableFlushPending(uint64_t* value, DBImpl* db, |
791 | | Version* version); |
792 | | bool HandleNumRunningFlushes(uint64_t* value, DBImpl* db, Version* version); |
793 | | bool HandleCompactionPending(uint64_t* value, DBImpl* db, Version* version); |
794 | | bool HandleNumRunningCompactions(uint64_t* value, DBImpl* db, |
795 | | Version* version); |
796 | | bool HandleBackgroundErrors(uint64_t* value, DBImpl* db, Version* version); |
797 | | bool HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* db, |
798 | | Version* version); |
799 | | bool HandleCurSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version); |
800 | | bool HandleSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version); |
801 | | bool HandleNumEntriesActiveMemTable(uint64_t* value, DBImpl* db, |
802 | | Version* version); |
803 | | bool HandleNumEntriesImmMemTables(uint64_t* value, DBImpl* db, |
804 | | Version* version); |
805 | | bool HandleNumDeletesActiveMemTable(uint64_t* value, DBImpl* db, |
806 | | Version* version); |
807 | | bool HandleNumDeletesImmMemTables(uint64_t* value, DBImpl* db, |
808 | | Version* version); |
809 | | bool HandleEstimateNumKeys(uint64_t* value, DBImpl* db, Version* version); |
810 | | bool HandleNumSnapshots(uint64_t* value, DBImpl* db, Version* version); |
811 | | bool HandleOldestSnapshotTime(uint64_t* value, DBImpl* db, Version* version); |
812 | | bool HandleOldestSnapshotSequence(uint64_t* value, DBImpl* db, |
813 | | Version* version); |
814 | | bool HandleNumLiveVersions(uint64_t* value, DBImpl* db, Version* version); |
815 | | bool HandleCurrentSuperVersionNumber(uint64_t* value, DBImpl* db, |
816 | | Version* version); |
817 | | bool HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db, |
818 | | Version* version); |
819 | | bool HandleBaseLevel(uint64_t* value, DBImpl* db, Version* version); |
820 | | bool HandleTotalSstFilesSize(uint64_t* value, DBImpl* db, Version* version); |
821 | | bool HandleLiveSstFilesSize(uint64_t* value, DBImpl* db, Version* version); |
822 | | bool HandleObsoleteSstFilesSize(uint64_t* value, DBImpl* db, |
823 | | Version* version); |
824 | | bool HandleEstimatePendingCompactionBytes(uint64_t* value, DBImpl* db, |
825 | | Version* version); |
826 | | bool HandleEstimateTableReadersMem(uint64_t* value, DBImpl* db, |
827 | | Version* version); |
828 | | bool HandleEstimateLiveDataSize(uint64_t* value, DBImpl* db, |
829 | | Version* version); |
830 | | bool HandleMinLogNumberToKeep(uint64_t* value, DBImpl* db, Version* version); |
831 | | bool HandleMinObsoleteSstNumberToKeep(uint64_t* value, DBImpl* db, |
832 | | Version* version); |
833 | | bool HandleActualDelayedWriteRate(uint64_t* value, DBImpl* db, |
834 | | Version* version); |
835 | | bool HandleIsWriteStopped(uint64_t* value, DBImpl* db, Version* version); |
836 | | bool HandleEstimateOldestKeyTime(uint64_t* value, DBImpl* db, |
837 | | Version* version); |
838 | | bool HandleBlockCacheCapacity(uint64_t* value, DBImpl* db, Version* version); |
839 | | bool HandleBlockCacheUsage(uint64_t* value, DBImpl* db, Version* version); |
840 | | bool HandleBlockCachePinnedUsage(uint64_t* value, DBImpl* db, |
841 | | Version* version); |
842 | | bool HandleBlockCacheEntryStatsInternal(std::string* value, bool fast); |
843 | | bool HandleBlockCacheEntryStatsMapInternal( |
844 | | std::map<std::string, std::string>* values, bool fast); |
845 | | bool HandleBlockCacheEntryStats(std::string* value, Slice suffix); |
846 | | bool HandleBlockCacheEntryStatsMap(std::map<std::string, std::string>* values, |
847 | | Slice suffix); |
848 | | bool HandleFastBlockCacheEntryStats(std::string* value, Slice suffix); |
849 | | bool HandleFastBlockCacheEntryStatsMap( |
850 | | std::map<std::string, std::string>* values, Slice suffix); |
851 | | bool HandleLiveSstFilesSizeAtTemperature(std::string* value, Slice suffix); |
852 | | bool HandleNumBlobFiles(uint64_t* value, DBImpl* db, Version* version); |
853 | | bool HandleBlobStats(std::string* value, Slice suffix); |
854 | | bool HandleTotalBlobFileSize(uint64_t* value, DBImpl* db, Version* version); |
855 | | bool HandleLiveBlobFileSize(uint64_t* value, DBImpl* db, Version* version); |
856 | | bool HandleLiveBlobFileGarbageSize(uint64_t* value, DBImpl* db, |
857 | | Version* version); |
858 | | bool HandleBlobCacheCapacity(uint64_t* value, DBImpl* db, Version* version); |
859 | | bool HandleBlobCacheUsage(uint64_t* value, DBImpl* db, Version* version); |
860 | | bool HandleBlobCachePinnedUsage(uint64_t* value, DBImpl* db, |
861 | | Version* version); |
862 | | |
863 | | // Total number of background errors encountered. Every time a flush task |
864 | | // or compaction task fails, this counter is incremented. The failure can |
865 | | // be caused by any possible reason, including file system errors, out of |
866 | | // resources, or input file corruption. Failing when retrying the same flush |
867 | | // or compaction will cause the counter to increase too. |
868 | | uint64_t bg_error_count_; |
869 | | |
870 | | const int number_levels_; |
871 | | SystemClock* clock_; |
872 | | ColumnFamilyData* cfd_; |
873 | | uint64_t started_at_; |
874 | | }; |
875 | | |
876 | | // IntPropertyAggregator aggregates an integer property across all column |
877 | | // families. |
878 | | class IntPropertyAggregator { |
879 | | public: |
880 | 0 | IntPropertyAggregator() {} |
881 | 0 | virtual ~IntPropertyAggregator() {} |
882 | | |
883 | | IntPropertyAggregator(const IntPropertyAggregator&) = delete; |
884 | | void operator=(const IntPropertyAggregator&) = delete; |
885 | | |
886 | | // Add a column family's property value to the aggregator. |
887 | | virtual void Add(ColumnFamilyData* cfd, uint64_t value) = 0; |
888 | | |
889 | | // Get the aggregated value. |
890 | | virtual uint64_t Aggregate() const = 0; |
891 | | }; |
892 | | |
893 | | std::unique_ptr<IntPropertyAggregator> CreateIntPropertyAggregator( |
894 | | const Slice& property); |
895 | | |
896 | | } // namespace ROCKSDB_NAMESPACE |