/src/rocksdb/db/internal_stats.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // This source code is licensed under both the GPLv2 (found in the |
2 | | // COPYING file in the root directory) and Apache 2.0 License |
3 | | // (found in the LICENSE.Apache file in the root directory). |
4 | | // |
5 | | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. |
6 | | // |
7 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
8 | | // Use of this source code is governed by a BSD-style license that can be |
9 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
10 | | |
11 | | #include "db/internal_stats.h" |
12 | | |
13 | | #include <algorithm> |
14 | | #include <cinttypes> |
15 | | #include <cstddef> |
16 | | #include <limits> |
17 | | #include <sstream> |
18 | | #include <string> |
19 | | #include <unordered_map> |
20 | | #include <utility> |
21 | | #include <vector> |
22 | | |
23 | | #include "cache/cache_entry_roles.h" |
24 | | #include "cache/cache_entry_stats.h" |
25 | | #include "db/column_family.h" |
26 | | #include "db/db_impl/db_impl.h" |
27 | | #include "db/write_stall_stats.h" |
28 | | #include "port/port.h" |
29 | | #include "rocksdb/system_clock.h" |
30 | | #include "rocksdb/table.h" |
31 | | #include "table/block_based/cachable_entry.h" |
32 | | #include "util/hash_containers.h" |
33 | | #include "util/string_util.h" |
34 | | |
35 | | namespace ROCKSDB_NAMESPACE { |
36 | | |
37 | | const std::map<LevelStatType, LevelStat> InternalStats::compaction_level_stats = |
38 | | { |
39 | | {LevelStatType::NUM_FILES, LevelStat{"NumFiles", "Files"}}, |
40 | | {LevelStatType::COMPACTED_FILES, |
41 | | LevelStat{"CompactedFiles", "CompactedFiles"}}, |
42 | | {LevelStatType::SIZE_BYTES, LevelStat{"SizeBytes", "Size"}}, |
43 | | {LevelStatType::SCORE, LevelStat{"Score", "Score"}}, |
44 | | {LevelStatType::READ_GB, LevelStat{"ReadGB", "Read(GB)"}}, |
45 | | {LevelStatType::RN_GB, LevelStat{"RnGB", "Rn(GB)"}}, |
46 | | {LevelStatType::RNP1_GB, LevelStat{"Rnp1GB", "Rnp1(GB)"}}, |
47 | | {LevelStatType::WRITE_GB, LevelStat{"WriteGB", "Write(GB)"}}, |
48 | | {LevelStatType::W_NEW_GB, LevelStat{"WnewGB", "Wnew(GB)"}}, |
49 | | {LevelStatType::MOVED_GB, LevelStat{"MovedGB", "Moved(GB)"}}, |
50 | | {LevelStatType::WRITE_AMP, LevelStat{"WriteAmp", "W-Amp"}}, |
51 | | {LevelStatType::READ_MBPS, LevelStat{"ReadMBps", "Rd(MB/s)"}}, |
52 | | {LevelStatType::WRITE_MBPS, LevelStat{"WriteMBps", "Wr(MB/s)"}}, |
53 | | {LevelStatType::COMP_SEC, LevelStat{"CompSec", "Comp(sec)"}}, |
54 | | {LevelStatType::COMP_CPU_SEC, |
55 | | LevelStat{"CompMergeCPU", "CompMergeCPU(sec)"}}, |
56 | | {LevelStatType::COMP_COUNT, LevelStat{"CompCount", "Comp(cnt)"}}, |
57 | | {LevelStatType::AVG_SEC, LevelStat{"AvgSec", "Avg(sec)"}}, |
58 | | {LevelStatType::KEY_IN, LevelStat{"KeyIn", "KeyIn"}}, |
59 | | {LevelStatType::KEY_DROP, LevelStat{"KeyDrop", "KeyDrop"}}, |
60 | | {LevelStatType::R_BLOB_GB, LevelStat{"RblobGB", "Rblob(GB)"}}, |
61 | | {LevelStatType::W_BLOB_GB, LevelStat{"WblobGB", "Wblob(GB)"}}, |
62 | | }; |
63 | | |
64 | | const std::map<InternalStats::InternalDBStatsType, DBStatInfo> |
65 | | InternalStats::db_stats_type_to_info = { |
66 | | {InternalStats::kIntStatsWalFileBytes, |
67 | | DBStatInfo{"db.wal_bytes_written"}}, |
68 | | {InternalStats::kIntStatsWalFileSynced, DBStatInfo{"db.wal_syncs"}}, |
69 | | {InternalStats::kIntStatsBytesWritten, |
70 | | DBStatInfo{"db.user_bytes_written"}}, |
71 | | {InternalStats::kIntStatsNumKeysWritten, |
72 | | DBStatInfo{"db.user_keys_written"}}, |
73 | | {InternalStats::kIntStatsWriteDoneByOther, |
74 | | DBStatInfo{"db.user_writes_by_other"}}, |
75 | | {InternalStats::kIntStatsWriteDoneBySelf, |
76 | | DBStatInfo{"db.user_writes_by_self"}}, |
77 | | {InternalStats::kIntStatsWriteWithWal, |
78 | | DBStatInfo{"db.user_writes_with_wal"}}, |
79 | | {InternalStats::kIntStatsWriteStallMicros, |
80 | | DBStatInfo{"db.user_write_stall_micros"}}, |
81 | | {InternalStats::kIntStatsWriteBufferManagerLimitStopsCounts, |
82 | | DBStatInfo{WriteStallStatsMapKeys::CauseConditionCount( |
83 | | WriteStallCause::kWriteBufferManagerLimit, |
84 | | WriteStallCondition::kStopped)}}, |
85 | | }; |
86 | | |
87 | | namespace { |
88 | | const double kMB = 1048576.0; |
89 | | const double kGB = kMB * 1024; |
90 | | const double kMicrosInSec = 1000000.0; |
91 | | |
92 | | void PrintLevelStatsHeader(char* buf, size_t len, const std::string& cf_name, |
93 | 120 | const std::string& group_by) { |
94 | 120 | int written_size = |
95 | 120 | snprintf(buf, len, "\n** Compaction Stats [%s] **\n", cf_name.c_str()); |
96 | 120 | written_size = std::min(written_size, static_cast<int>(len)); |
97 | 2.40k | auto hdr = [](LevelStatType t) { |
98 | 2.40k | return InternalStats::compaction_level_stats.at(t).header_name.c_str(); |
99 | 2.40k | }; |
100 | 120 | int line_size = snprintf( |
101 | 120 | buf + written_size, len - written_size, |
102 | 120 | "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s " |
103 | 120 | "%s\n", |
104 | | // Note that we skip COMPACTED_FILES and merge it with Files column |
105 | 120 | group_by.c_str(), hdr(LevelStatType::NUM_FILES), |
106 | 120 | hdr(LevelStatType::SIZE_BYTES), hdr(LevelStatType::SCORE), |
107 | 120 | hdr(LevelStatType::READ_GB), hdr(LevelStatType::RN_GB), |
108 | 120 | hdr(LevelStatType::RNP1_GB), hdr(LevelStatType::WRITE_GB), |
109 | 120 | hdr(LevelStatType::W_NEW_GB), hdr(LevelStatType::MOVED_GB), |
110 | 120 | hdr(LevelStatType::WRITE_AMP), hdr(LevelStatType::READ_MBPS), |
111 | 120 | hdr(LevelStatType::WRITE_MBPS), hdr(LevelStatType::COMP_SEC), |
112 | 120 | hdr(LevelStatType::COMP_CPU_SEC), hdr(LevelStatType::COMP_COUNT), |
113 | 120 | hdr(LevelStatType::AVG_SEC), hdr(LevelStatType::KEY_IN), |
114 | 120 | hdr(LevelStatType::KEY_DROP), hdr(LevelStatType::R_BLOB_GB), |
115 | 120 | hdr(LevelStatType::W_BLOB_GB)); |
116 | | |
117 | 120 | written_size += line_size; |
118 | 120 | written_size = std::min(written_size, static_cast<int>(len)); |
119 | 120 | snprintf(buf + written_size, len - written_size, "%s\n", |
120 | 120 | std::string(line_size, '-').c_str()); |
121 | 120 | } |
122 | | |
123 | | void PrepareLevelStats(std::map<LevelStatType, double>* level_stats, |
124 | | int num_files, int being_compacted, |
125 | | double total_file_size, double score, double w_amp, |
126 | 130 | const InternalStats::CompactionStats& stats) { |
127 | 130 | const uint64_t bytes_read = stats.bytes_read_non_output_levels + |
128 | 130 | stats.bytes_read_output_level + |
129 | 130 | stats.bytes_read_blob; |
130 | 130 | const uint64_t bytes_written = stats.bytes_written + stats.bytes_written_blob; |
131 | 130 | const int64_t bytes_new = stats.bytes_written - stats.bytes_read_output_level; |
132 | 130 | const double elapsed = (stats.micros + 1) / kMicrosInSec; |
133 | | |
134 | 130 | (*level_stats)[LevelStatType::NUM_FILES] = num_files; |
135 | 130 | (*level_stats)[LevelStatType::COMPACTED_FILES] = being_compacted; |
136 | 130 | (*level_stats)[LevelStatType::SIZE_BYTES] = total_file_size; |
137 | 130 | (*level_stats)[LevelStatType::SCORE] = score; |
138 | 130 | (*level_stats)[LevelStatType::READ_GB] = bytes_read / kGB; |
139 | 130 | (*level_stats)[LevelStatType::RN_GB] = |
140 | 130 | stats.bytes_read_non_output_levels / kGB; |
141 | 130 | (*level_stats)[LevelStatType::RNP1_GB] = stats.bytes_read_output_level / kGB; |
142 | 130 | (*level_stats)[LevelStatType::WRITE_GB] = stats.bytes_written / kGB; |
143 | 130 | (*level_stats)[LevelStatType::W_NEW_GB] = bytes_new / kGB; |
144 | 130 | (*level_stats)[LevelStatType::MOVED_GB] = stats.bytes_moved / kGB; |
145 | 130 | (*level_stats)[LevelStatType::WRITE_AMP] = w_amp; |
146 | 130 | (*level_stats)[LevelStatType::READ_MBPS] = bytes_read / kMB / elapsed; |
147 | 130 | (*level_stats)[LevelStatType::WRITE_MBPS] = bytes_written / kMB / elapsed; |
148 | 130 | (*level_stats)[LevelStatType::COMP_SEC] = stats.micros / kMicrosInSec; |
149 | 130 | (*level_stats)[LevelStatType::COMP_CPU_SEC] = stats.cpu_micros / kMicrosInSec; |
150 | 130 | (*level_stats)[LevelStatType::COMP_COUNT] = stats.count; |
151 | 130 | (*level_stats)[LevelStatType::AVG_SEC] = |
152 | 130 | stats.count == 0 ? 0 : stats.micros / kMicrosInSec / stats.count; |
153 | 130 | (*level_stats)[LevelStatType::KEY_IN] = |
154 | 130 | static_cast<double>(stats.num_input_records); |
155 | 130 | (*level_stats)[LevelStatType::KEY_DROP] = |
156 | 130 | static_cast<double>(stats.num_dropped_records); |
157 | 130 | (*level_stats)[LevelStatType::R_BLOB_GB] = stats.bytes_read_blob / kGB; |
158 | 130 | (*level_stats)[LevelStatType::W_BLOB_GB] = stats.bytes_written_blob / kGB; |
159 | 130 | } |
160 | | |
161 | | void PrintLevelStats(char* buf, size_t len, const std::string& name, |
162 | 130 | const std::map<LevelStatType, double>& stat_value) { |
163 | 130 | snprintf( |
164 | 130 | buf, len, |
165 | 130 | "%4s " /* Level */ |
166 | 130 | "%6d/%-3d " /* Files */ |
167 | 130 | "%8s " /* Size */ |
168 | 130 | "%5.1f " /* Score */ |
169 | 130 | "%8.1f " /* Read(GB) */ |
170 | 130 | "%7.1f " /* Rn(GB) */ |
171 | 130 | "%8.1f " /* Rnp1(GB) */ |
172 | 130 | "%9.1f " /* Write(GB) */ |
173 | 130 | "%8.1f " /* Wnew(GB) */ |
174 | 130 | "%9.1f " /* Moved(GB) */ |
175 | 130 | "%5.1f " /* W-Amp */ |
176 | 130 | "%8.1f " /* Rd(MB/s) */ |
177 | 130 | "%8.1f " /* Wr(MB/s) */ |
178 | 130 | "%9.2f " /* Comp(sec) */ |
179 | 130 | "%17.2f " /* CompMergeCPU(sec) */ |
180 | 130 | "%9d " /* Comp(cnt) */ |
181 | 130 | "%8.3f " /* Avg(sec) */ |
182 | 130 | "%7s " /* KeyIn */ |
183 | 130 | "%6s " /* KeyDrop */ |
184 | 130 | "%9.1f " /* Rblob(GB) */ |
185 | 130 | "%9.1f\n", /* Wblob(GB) */ |
186 | 130 | name.c_str(), static_cast<int>(stat_value.at(LevelStatType::NUM_FILES)), |
187 | 130 | static_cast<int>(stat_value.at(LevelStatType::COMPACTED_FILES)), |
188 | 130 | BytesToHumanString( |
189 | 130 | static_cast<uint64_t>(stat_value.at(LevelStatType::SIZE_BYTES))) |
190 | 130 | .c_str(), |
191 | 130 | stat_value.at(LevelStatType::SCORE), |
192 | 130 | stat_value.at(LevelStatType::READ_GB), |
193 | 130 | stat_value.at(LevelStatType::RN_GB), |
194 | 130 | stat_value.at(LevelStatType::RNP1_GB), |
195 | 130 | stat_value.at(LevelStatType::WRITE_GB), |
196 | 130 | stat_value.at(LevelStatType::W_NEW_GB), |
197 | 130 | stat_value.at(LevelStatType::MOVED_GB), |
198 | 130 | stat_value.at(LevelStatType::WRITE_AMP), |
199 | 130 | stat_value.at(LevelStatType::READ_MBPS), |
200 | 130 | stat_value.at(LevelStatType::WRITE_MBPS), |
201 | 130 | stat_value.at(LevelStatType::COMP_SEC), |
202 | 130 | stat_value.at(LevelStatType::COMP_CPU_SEC), |
203 | 130 | static_cast<int>(stat_value.at(LevelStatType::COMP_COUNT)), |
204 | 130 | stat_value.at(LevelStatType::AVG_SEC), |
205 | 130 | NumberToHumanString( |
206 | 130 | static_cast<std::int64_t>(stat_value.at(LevelStatType::KEY_IN))) |
207 | 130 | .c_str(), |
208 | 130 | NumberToHumanString( |
209 | 130 | static_cast<std::int64_t>(stat_value.at(LevelStatType::KEY_DROP))) |
210 | 130 | .c_str(), |
211 | 130 | stat_value.at(LevelStatType::R_BLOB_GB), |
212 | 130 | stat_value.at(LevelStatType::W_BLOB_GB)); |
213 | 130 | } |
214 | | |
215 | | void PrintLevelStats(char* buf, size_t len, const std::string& name, |
216 | | int num_files, int being_compacted, double total_file_size, |
217 | | double score, double w_amp, |
218 | 60 | const InternalStats::CompactionStats& stats) { |
219 | 60 | std::map<LevelStatType, double> level_stats; |
220 | 60 | PrepareLevelStats(&level_stats, num_files, being_compacted, total_file_size, |
221 | 60 | score, w_amp, stats); |
222 | 60 | PrintLevelStats(buf, len, name, level_stats); |
223 | 60 | } |
224 | | |
225 | | // Assumes that trailing numbers represent an optional argument. This requires |
226 | | // property names to not end with numbers. |
227 | 498 | std::pair<Slice, Slice> GetPropertyNameAndArg(const Slice& property) { |
228 | 498 | Slice name = property, arg = property; |
229 | 498 | size_t sfx_len = 0; |
230 | 501 | while (sfx_len < property.size() && |
231 | 501 | isdigit(property[property.size() - sfx_len - 1])) { |
232 | 3 | ++sfx_len; |
233 | 3 | } |
234 | 498 | name.remove_suffix(sfx_len); |
235 | 498 | arg.remove_prefix(property.size() - sfx_len); |
236 | 498 | return {name, arg}; |
237 | 498 | } |
238 | | } // anonymous namespace |
239 | | |
240 | | static const std::string rocksdb_prefix = "rocksdb."; |
241 | | |
242 | | static const std::string num_files_at_level_prefix = "num-files-at-level"; |
243 | | static const std::string compression_ratio_at_level_prefix = |
244 | | "compression-ratio-at-level"; |
245 | | static const std::string allstats = "stats"; |
246 | | static const std::string sstables = "sstables"; |
247 | | static const std::string cfstats = "cfstats"; |
248 | | static const std::string cfstats_no_file_histogram = |
249 | | "cfstats-no-file-histogram"; |
250 | | static const std::string cf_file_histogram = "cf-file-histogram"; |
251 | | static const std::string cf_write_stall_stats = "cf-write-stall-stats"; |
252 | | static const std::string dbstats = "dbstats"; |
253 | | static const std::string db_write_stall_stats = "db-write-stall-stats"; |
254 | | static const std::string levelstats = "levelstats"; |
255 | | static const std::string block_cache_entry_stats = "block-cache-entry-stats"; |
256 | | static const std::string fast_block_cache_entry_stats = |
257 | | "fast-block-cache-entry-stats"; |
258 | | static const std::string num_immutable_mem_table = "num-immutable-mem-table"; |
259 | | static const std::string num_immutable_mem_table_flushed = |
260 | | "num-immutable-mem-table-flushed"; |
261 | | static const std::string mem_table_flush_pending = "mem-table-flush-pending"; |
262 | | static const std::string compaction_pending = "compaction-pending"; |
263 | | static const std::string background_errors = "background-errors"; |
264 | | static const std::string cur_size_active_mem_table = |
265 | | "cur-size-active-mem-table"; |
266 | | static const std::string cur_size_all_mem_tables = "cur-size-all-mem-tables"; |
267 | | static const std::string size_all_mem_tables = "size-all-mem-tables"; |
268 | | static const std::string num_entries_active_mem_table = |
269 | | "num-entries-active-mem-table"; |
270 | | static const std::string num_entries_imm_mem_tables = |
271 | | "num-entries-imm-mem-tables"; |
272 | | static const std::string num_deletes_active_mem_table = |
273 | | "num-deletes-active-mem-table"; |
274 | | static const std::string num_deletes_imm_mem_tables = |
275 | | "num-deletes-imm-mem-tables"; |
276 | | static const std::string estimate_num_keys = "estimate-num-keys"; |
277 | | static const std::string estimate_table_readers_mem = |
278 | | "estimate-table-readers-mem"; |
279 | | static const std::string is_file_deletions_enabled = |
280 | | "is-file-deletions-enabled"; |
281 | | static const std::string num_snapshots = "num-snapshots"; |
282 | | static const std::string oldest_snapshot_time = "oldest-snapshot-time"; |
283 | | static const std::string oldest_snapshot_sequence = "oldest-snapshot-sequence"; |
284 | | static const std::string num_live_versions = "num-live-versions"; |
285 | | static const std::string current_version_number = |
286 | | "current-super-version-number"; |
287 | | static const std::string estimate_live_data_size = "estimate-live-data-size"; |
288 | | static const std::string min_log_number_to_keep_str = "min-log-number-to-keep"; |
289 | | static const std::string min_obsolete_sst_number_to_keep_str = |
290 | | "min-obsolete-sst-number-to-keep"; |
291 | | static const std::string base_level_str = "base-level"; |
292 | | static const std::string total_sst_files_size = "total-sst-files-size"; |
293 | | static const std::string live_sst_files_size = "live-sst-files-size"; |
294 | | static const std::string obsolete_sst_files_size = "obsolete-sst-files-size"; |
295 | | static const std::string live_sst_files_size_at_temperature = |
296 | | "live-sst-files-size-at-temperature"; |
297 | | static const std::string estimate_pending_comp_bytes = |
298 | | "estimate-pending-compaction-bytes"; |
299 | | static const std::string aggregated_table_properties = |
300 | | "aggregated-table-properties"; |
301 | | static const std::string aggregated_table_properties_at_level = |
302 | | aggregated_table_properties + "-at-level"; |
303 | | static const std::string num_running_compactions = "num-running-compactions"; |
304 | | static const std::string num_running_flushes = "num-running-flushes"; |
305 | | static const std::string actual_delayed_write_rate = |
306 | | "actual-delayed-write-rate"; |
307 | | static const std::string is_write_stopped = "is-write-stopped"; |
308 | | static const std::string estimate_oldest_key_time = "estimate-oldest-key-time"; |
309 | | static const std::string block_cache_capacity = "block-cache-capacity"; |
310 | | static const std::string block_cache_usage = "block-cache-usage"; |
311 | | static const std::string block_cache_pinned_usage = "block-cache-pinned-usage"; |
312 | | static const std::string options_statistics = "options-statistics"; |
313 | | static const std::string num_blob_files = "num-blob-files"; |
314 | | static const std::string blob_stats = "blob-stats"; |
315 | | static const std::string total_blob_file_size = "total-blob-file-size"; |
316 | | static const std::string live_blob_file_size = "live-blob-file-size"; |
317 | | static const std::string live_blob_file_garbage_size = |
318 | | "live-blob-file-garbage-size"; |
319 | | static const std::string blob_cache_capacity = "blob-cache-capacity"; |
320 | | static const std::string blob_cache_usage = "blob-cache-usage"; |
321 | | static const std::string blob_cache_pinned_usage = "blob-cache-pinned-usage"; |
322 | | |
323 | | const std::string DB::Properties::kNumFilesAtLevelPrefix = |
324 | | rocksdb_prefix + num_files_at_level_prefix; |
325 | | const std::string DB::Properties::kCompressionRatioAtLevelPrefix = |
326 | | rocksdb_prefix + compression_ratio_at_level_prefix; |
327 | | const std::string DB::Properties::kStats = rocksdb_prefix + allstats; |
328 | | const std::string DB::Properties::kSSTables = rocksdb_prefix + sstables; |
329 | | const std::string DB::Properties::kCFStats = rocksdb_prefix + cfstats; |
330 | | const std::string DB::Properties::kCFStatsNoFileHistogram = |
331 | | rocksdb_prefix + cfstats_no_file_histogram; |
332 | | const std::string DB::Properties::kCFFileHistogram = |
333 | | rocksdb_prefix + cf_file_histogram; |
334 | | const std::string DB::Properties::kCFWriteStallStats = |
335 | | rocksdb_prefix + cf_write_stall_stats; |
336 | | const std::string DB::Properties::kDBWriteStallStats = |
337 | | rocksdb_prefix + db_write_stall_stats; |
338 | | const std::string DB::Properties::kDBStats = rocksdb_prefix + dbstats; |
339 | | const std::string DB::Properties::kLevelStats = rocksdb_prefix + levelstats; |
340 | | const std::string DB::Properties::kBlockCacheEntryStats = |
341 | | rocksdb_prefix + block_cache_entry_stats; |
342 | | const std::string DB::Properties::kFastBlockCacheEntryStats = |
343 | | rocksdb_prefix + fast_block_cache_entry_stats; |
344 | | const std::string DB::Properties::kNumImmutableMemTable = |
345 | | rocksdb_prefix + num_immutable_mem_table; |
346 | | const std::string DB::Properties::kNumImmutableMemTableFlushed = |
347 | | rocksdb_prefix + num_immutable_mem_table_flushed; |
348 | | const std::string DB::Properties::kMemTableFlushPending = |
349 | | rocksdb_prefix + mem_table_flush_pending; |
350 | | const std::string DB::Properties::kCompactionPending = |
351 | | rocksdb_prefix + compaction_pending; |
352 | | const std::string DB::Properties::kNumRunningCompactions = |
353 | | rocksdb_prefix + num_running_compactions; |
354 | | const std::string DB::Properties::kNumRunningFlushes = |
355 | | rocksdb_prefix + num_running_flushes; |
356 | | const std::string DB::Properties::kBackgroundErrors = |
357 | | rocksdb_prefix + background_errors; |
358 | | const std::string DB::Properties::kCurSizeActiveMemTable = |
359 | | rocksdb_prefix + cur_size_active_mem_table; |
360 | | const std::string DB::Properties::kCurSizeAllMemTables = |
361 | | rocksdb_prefix + cur_size_all_mem_tables; |
362 | | const std::string DB::Properties::kSizeAllMemTables = |
363 | | rocksdb_prefix + size_all_mem_tables; |
364 | | const std::string DB::Properties::kNumEntriesActiveMemTable = |
365 | | rocksdb_prefix + num_entries_active_mem_table; |
366 | | const std::string DB::Properties::kNumEntriesImmMemTables = |
367 | | rocksdb_prefix + num_entries_imm_mem_tables; |
368 | | const std::string DB::Properties::kNumDeletesActiveMemTable = |
369 | | rocksdb_prefix + num_deletes_active_mem_table; |
370 | | const std::string DB::Properties::kNumDeletesImmMemTables = |
371 | | rocksdb_prefix + num_deletes_imm_mem_tables; |
372 | | const std::string DB::Properties::kEstimateNumKeys = |
373 | | rocksdb_prefix + estimate_num_keys; |
374 | | const std::string DB::Properties::kEstimateTableReadersMem = |
375 | | rocksdb_prefix + estimate_table_readers_mem; |
376 | | const std::string DB::Properties::kIsFileDeletionsEnabled = |
377 | | rocksdb_prefix + is_file_deletions_enabled; |
378 | | const std::string DB::Properties::kNumSnapshots = |
379 | | rocksdb_prefix + num_snapshots; |
380 | | const std::string DB::Properties::kOldestSnapshotTime = |
381 | | rocksdb_prefix + oldest_snapshot_time; |
382 | | const std::string DB::Properties::kOldestSnapshotSequence = |
383 | | rocksdb_prefix + oldest_snapshot_sequence; |
384 | | const std::string DB::Properties::kNumLiveVersions = |
385 | | rocksdb_prefix + num_live_versions; |
386 | | const std::string DB::Properties::kCurrentSuperVersionNumber = |
387 | | rocksdb_prefix + current_version_number; |
388 | | const std::string DB::Properties::kEstimateLiveDataSize = |
389 | | rocksdb_prefix + estimate_live_data_size; |
390 | | const std::string DB::Properties::kMinLogNumberToKeep = |
391 | | rocksdb_prefix + min_log_number_to_keep_str; |
392 | | const std::string DB::Properties::kMinObsoleteSstNumberToKeep = |
393 | | rocksdb_prefix + min_obsolete_sst_number_to_keep_str; |
394 | | const std::string DB::Properties::kTotalSstFilesSize = |
395 | | rocksdb_prefix + total_sst_files_size; |
396 | | const std::string DB::Properties::kLiveSstFilesSize = |
397 | | rocksdb_prefix + live_sst_files_size; |
398 | | const std::string DB::Properties::kObsoleteSstFilesSize = |
399 | | rocksdb_prefix + obsolete_sst_files_size; |
400 | | const std::string DB::Properties::kBaseLevel = rocksdb_prefix + base_level_str; |
401 | | const std::string DB::Properties::kEstimatePendingCompactionBytes = |
402 | | rocksdb_prefix + estimate_pending_comp_bytes; |
403 | | const std::string DB::Properties::kAggregatedTableProperties = |
404 | | rocksdb_prefix + aggregated_table_properties; |
405 | | const std::string DB::Properties::kAggregatedTablePropertiesAtLevel = |
406 | | rocksdb_prefix + aggregated_table_properties_at_level; |
407 | | const std::string DB::Properties::kActualDelayedWriteRate = |
408 | | rocksdb_prefix + actual_delayed_write_rate; |
409 | | const std::string DB::Properties::kIsWriteStopped = |
410 | | rocksdb_prefix + is_write_stopped; |
411 | | const std::string DB::Properties::kEstimateOldestKeyTime = |
412 | | rocksdb_prefix + estimate_oldest_key_time; |
413 | | const std::string DB::Properties::kBlockCacheCapacity = |
414 | | rocksdb_prefix + block_cache_capacity; |
415 | | const std::string DB::Properties::kBlockCacheUsage = |
416 | | rocksdb_prefix + block_cache_usage; |
417 | | const std::string DB::Properties::kBlockCachePinnedUsage = |
418 | | rocksdb_prefix + block_cache_pinned_usage; |
419 | | const std::string DB::Properties::kOptionsStatistics = |
420 | | rocksdb_prefix + options_statistics; |
421 | | const std::string DB::Properties::kLiveSstFilesSizeAtTemperature = |
422 | | rocksdb_prefix + live_sst_files_size_at_temperature; |
423 | | const std::string DB::Properties::kNumBlobFiles = |
424 | | rocksdb_prefix + num_blob_files; |
425 | | const std::string DB::Properties::kBlobStats = rocksdb_prefix + blob_stats; |
426 | | const std::string DB::Properties::kTotalBlobFileSize = |
427 | | rocksdb_prefix + total_blob_file_size; |
428 | | const std::string DB::Properties::kLiveBlobFileSize = |
429 | | rocksdb_prefix + live_blob_file_size; |
430 | | const std::string DB::Properties::kLiveBlobFileGarbageSize = |
431 | | rocksdb_prefix + live_blob_file_garbage_size; |
432 | | const std::string DB::Properties::kBlobCacheCapacity = |
433 | | rocksdb_prefix + blob_cache_capacity; |
434 | | const std::string DB::Properties::kBlobCacheUsage = |
435 | | rocksdb_prefix + blob_cache_usage; |
436 | | const std::string DB::Properties::kBlobCachePinnedUsage = |
437 | | rocksdb_prefix + blob_cache_pinned_usage; |
438 | | |
439 | | const std::string InternalStats::kPeriodicCFStats = |
440 | | DB::Properties::kCFStats + ".periodic"; |
441 | | const int InternalStats::kMaxNoChangePeriodSinceDump = 8; |
442 | | |
443 | | const UnorderedMap<std::string, DBPropertyInfo> |
444 | | InternalStats::ppt_name_to_info = { |
445 | | {DB::Properties::kNumFilesAtLevelPrefix, |
446 | | {false, &InternalStats::HandleNumFilesAtLevel, nullptr, nullptr, |
447 | | nullptr}}, |
448 | | {DB::Properties::kCompressionRatioAtLevelPrefix, |
449 | | {false, &InternalStats::HandleCompressionRatioAtLevelPrefix, nullptr, |
450 | | nullptr, nullptr}}, |
451 | | {DB::Properties::kLevelStats, |
452 | | {false, &InternalStats::HandleLevelStats, nullptr, nullptr, nullptr}}, |
453 | | {DB::Properties::kStats, |
454 | | {false, &InternalStats::HandleStats, nullptr, nullptr, nullptr}}, |
455 | | {DB::Properties::kCFStats, |
456 | | {false, &InternalStats::HandleCFStats, nullptr, |
457 | | &InternalStats::HandleCFMapStats, nullptr}}, |
458 | | {InternalStats::kPeriodicCFStats, |
459 | | {false, &InternalStats::HandleCFStatsPeriodic, nullptr, nullptr, |
460 | | nullptr}}, |
461 | | {DB::Properties::kCFStatsNoFileHistogram, |
462 | | {false, &InternalStats::HandleCFStatsNoFileHistogram, nullptr, nullptr, |
463 | | nullptr}}, |
464 | | {DB::Properties::kCFFileHistogram, |
465 | | {false, &InternalStats::HandleCFFileHistogram, nullptr, nullptr, |
466 | | nullptr}}, |
467 | | {DB::Properties::kCFWriteStallStats, |
468 | | {false, &InternalStats::HandleCFWriteStallStats, nullptr, |
469 | | &InternalStats::HandleCFWriteStallStatsMap, nullptr}}, |
470 | | {DB::Properties::kDBStats, |
471 | | {false, &InternalStats::HandleDBStats, nullptr, |
472 | | &InternalStats::HandleDBMapStats, nullptr}}, |
473 | | {DB::Properties::kDBWriteStallStats, |
474 | | {false, &InternalStats::HandleDBWriteStallStats, nullptr, |
475 | | &InternalStats::HandleDBWriteStallStatsMap, nullptr}}, |
476 | | {DB::Properties::kBlockCacheEntryStats, |
477 | | {true, &InternalStats::HandleBlockCacheEntryStats, nullptr, |
478 | | &InternalStats::HandleBlockCacheEntryStatsMap, nullptr}}, |
479 | | {DB::Properties::kFastBlockCacheEntryStats, |
480 | | {true, &InternalStats::HandleFastBlockCacheEntryStats, nullptr, |
481 | | &InternalStats::HandleFastBlockCacheEntryStatsMap, nullptr}}, |
482 | | {DB::Properties::kSSTables, |
483 | | {false, &InternalStats::HandleSsTables, nullptr, nullptr, nullptr}}, |
484 | | {DB::Properties::kAggregatedTableProperties, |
485 | | {false, &InternalStats::HandleAggregatedTableProperties, nullptr, |
486 | | &InternalStats::HandleAggregatedTablePropertiesMap, nullptr}}, |
487 | | {DB::Properties::kAggregatedTablePropertiesAtLevel, |
488 | | {false, &InternalStats::HandleAggregatedTablePropertiesAtLevel, |
489 | | nullptr, &InternalStats::HandleAggregatedTablePropertiesAtLevelMap, |
490 | | nullptr}}, |
491 | | {DB::Properties::kNumImmutableMemTable, |
492 | | {false, nullptr, &InternalStats::HandleNumImmutableMemTable, nullptr, |
493 | | nullptr}}, |
494 | | {DB::Properties::kNumImmutableMemTableFlushed, |
495 | | {false, nullptr, &InternalStats::HandleNumImmutableMemTableFlushed, |
496 | | nullptr, nullptr}}, |
497 | | {DB::Properties::kMemTableFlushPending, |
498 | | {false, nullptr, &InternalStats::HandleMemTableFlushPending, nullptr, |
499 | | nullptr}}, |
500 | | {DB::Properties::kCompactionPending, |
501 | | {false, nullptr, &InternalStats::HandleCompactionPending, nullptr, |
502 | | nullptr}}, |
503 | | {DB::Properties::kBackgroundErrors, |
504 | | {false, nullptr, &InternalStats::HandleBackgroundErrors, nullptr, |
505 | | nullptr}}, |
506 | | {DB::Properties::kCurSizeActiveMemTable, |
507 | | {false, nullptr, &InternalStats::HandleCurSizeActiveMemTable, nullptr, |
508 | | nullptr}}, |
509 | | {DB::Properties::kCurSizeAllMemTables, |
510 | | {false, nullptr, &InternalStats::HandleCurSizeAllMemTables, nullptr, |
511 | | nullptr}}, |
512 | | {DB::Properties::kSizeAllMemTables, |
513 | | {false, nullptr, &InternalStats::HandleSizeAllMemTables, nullptr, |
514 | | nullptr}}, |
515 | | {DB::Properties::kNumEntriesActiveMemTable, |
516 | | {false, nullptr, &InternalStats::HandleNumEntriesActiveMemTable, |
517 | | nullptr, nullptr}}, |
518 | | {DB::Properties::kNumEntriesImmMemTables, |
519 | | {false, nullptr, &InternalStats::HandleNumEntriesImmMemTables, nullptr, |
520 | | nullptr}}, |
521 | | {DB::Properties::kNumDeletesActiveMemTable, |
522 | | {false, nullptr, &InternalStats::HandleNumDeletesActiveMemTable, |
523 | | nullptr, nullptr}}, |
524 | | {DB::Properties::kNumDeletesImmMemTables, |
525 | | {false, nullptr, &InternalStats::HandleNumDeletesImmMemTables, nullptr, |
526 | | nullptr}}, |
527 | | {DB::Properties::kEstimateNumKeys, |
528 | | {false, nullptr, &InternalStats::HandleEstimateNumKeys, nullptr, |
529 | | nullptr}}, |
530 | | {DB::Properties::kEstimateTableReadersMem, |
531 | | {true, nullptr, &InternalStats::HandleEstimateTableReadersMem, nullptr, |
532 | | nullptr}}, |
533 | | {DB::Properties::kIsFileDeletionsEnabled, |
534 | | {false, nullptr, &InternalStats::HandleIsFileDeletionsEnabled, nullptr, |
535 | | nullptr}}, |
536 | | {DB::Properties::kNumSnapshots, |
537 | | {false, nullptr, &InternalStats::HandleNumSnapshots, nullptr, |
538 | | nullptr}}, |
539 | | {DB::Properties::kOldestSnapshotTime, |
540 | | {false, nullptr, &InternalStats::HandleOldestSnapshotTime, nullptr, |
541 | | nullptr}}, |
542 | | {DB::Properties::kOldestSnapshotSequence, |
543 | | {false, nullptr, &InternalStats::HandleOldestSnapshotSequence, nullptr, |
544 | | nullptr}}, |
545 | | {DB::Properties::kNumLiveVersions, |
546 | | {false, nullptr, &InternalStats::HandleNumLiveVersions, nullptr, |
547 | | nullptr}}, |
548 | | {DB::Properties::kCurrentSuperVersionNumber, |
549 | | {false, nullptr, &InternalStats::HandleCurrentSuperVersionNumber, |
550 | | nullptr, nullptr}}, |
551 | | {DB::Properties::kEstimateLiveDataSize, |
552 | | {true, nullptr, &InternalStats::HandleEstimateLiveDataSize, nullptr, |
553 | | nullptr}}, |
554 | | {DB::Properties::kMinLogNumberToKeep, |
555 | | {false, nullptr, &InternalStats::HandleMinLogNumberToKeep, nullptr, |
556 | | nullptr}}, |
557 | | {DB::Properties::kMinObsoleteSstNumberToKeep, |
558 | | {false, nullptr, &InternalStats::HandleMinObsoleteSstNumberToKeep, |
559 | | nullptr, nullptr}}, |
560 | | {DB::Properties::kBaseLevel, |
561 | | {false, nullptr, &InternalStats::HandleBaseLevel, nullptr, nullptr}}, |
562 | | {DB::Properties::kTotalSstFilesSize, |
563 | | {false, nullptr, &InternalStats::HandleTotalSstFilesSize, nullptr, |
564 | | nullptr}}, |
565 | | {DB::Properties::kLiveSstFilesSize, |
566 | | {false, nullptr, &InternalStats::HandleLiveSstFilesSize, nullptr, |
567 | | nullptr}}, |
568 | | {DB::Properties::kLiveSstFilesSizeAtTemperature, |
569 | | {false, &InternalStats::HandleLiveSstFilesSizeAtTemperature, nullptr, |
570 | | nullptr, nullptr}}, |
571 | | {DB::Properties::kObsoleteSstFilesSize, |
572 | | {false, nullptr, &InternalStats::HandleObsoleteSstFilesSize, nullptr, |
573 | | nullptr}}, |
574 | | {DB::Properties::kEstimatePendingCompactionBytes, |
575 | | {false, nullptr, &InternalStats::HandleEstimatePendingCompactionBytes, |
576 | | nullptr, nullptr}}, |
577 | | {DB::Properties::kNumRunningFlushes, |
578 | | {false, nullptr, &InternalStats::HandleNumRunningFlushes, nullptr, |
579 | | nullptr}}, |
580 | | {DB::Properties::kNumRunningCompactions, |
581 | | {false, nullptr, &InternalStats::HandleNumRunningCompactions, nullptr, |
582 | | nullptr}}, |
583 | | {DB::Properties::kActualDelayedWriteRate, |
584 | | {false, nullptr, &InternalStats::HandleActualDelayedWriteRate, nullptr, |
585 | | nullptr}}, |
586 | | {DB::Properties::kIsWriteStopped, |
587 | | {false, nullptr, &InternalStats::HandleIsWriteStopped, nullptr, |
588 | | nullptr}}, |
589 | | {DB::Properties::kEstimateOldestKeyTime, |
590 | | {false, nullptr, &InternalStats::HandleEstimateOldestKeyTime, nullptr, |
591 | | nullptr}}, |
592 | | {DB::Properties::kBlockCacheCapacity, |
593 | | {false, nullptr, &InternalStats::HandleBlockCacheCapacity, nullptr, |
594 | | nullptr}}, |
595 | | {DB::Properties::kBlockCacheUsage, |
596 | | {false, nullptr, &InternalStats::HandleBlockCacheUsage, nullptr, |
597 | | nullptr}}, |
598 | | {DB::Properties::kBlockCachePinnedUsage, |
599 | | {false, nullptr, &InternalStats::HandleBlockCachePinnedUsage, nullptr, |
600 | | nullptr}}, |
601 | | {DB::Properties::kOptionsStatistics, |
602 | | {true, nullptr, nullptr, nullptr, |
603 | | &DBImpl::GetPropertyHandleOptionsStatistics}}, |
604 | | {DB::Properties::kNumBlobFiles, |
605 | | {false, nullptr, &InternalStats::HandleNumBlobFiles, nullptr, |
606 | | nullptr}}, |
607 | | {DB::Properties::kBlobStats, |
608 | | {false, &InternalStats::HandleBlobStats, nullptr, nullptr, nullptr}}, |
609 | | {DB::Properties::kTotalBlobFileSize, |
610 | | {false, nullptr, &InternalStats::HandleTotalBlobFileSize, nullptr, |
611 | | nullptr}}, |
612 | | {DB::Properties::kLiveBlobFileSize, |
613 | | {false, nullptr, &InternalStats::HandleLiveBlobFileSize, nullptr, |
614 | | nullptr}}, |
615 | | {DB::Properties::kLiveBlobFileGarbageSize, |
616 | | {false, nullptr, &InternalStats::HandleLiveBlobFileGarbageSize, |
617 | | nullptr, nullptr}}, |
618 | | {DB::Properties::kBlobCacheCapacity, |
619 | | {false, nullptr, &InternalStats::HandleBlobCacheCapacity, nullptr, |
620 | | nullptr}}, |
621 | | {DB::Properties::kBlobCacheUsage, |
622 | | {false, nullptr, &InternalStats::HandleBlobCacheUsage, nullptr, |
623 | | nullptr}}, |
624 | | {DB::Properties::kBlobCachePinnedUsage, |
625 | | {false, nullptr, &InternalStats::HandleBlobCachePinnedUsage, nullptr, |
626 | | nullptr}}, |
627 | | }; |
628 | | |
629 | | InternalStats::InternalStats(int num_levels, SystemClock* clock, |
630 | | ColumnFamilyData* cfd) |
631 | | : db_stats_{}, |
632 | | cf_stats_value_{}, |
633 | | cf_stats_count_{}, |
634 | | comp_stats_(num_levels), |
635 | | comp_stats_by_pri_(Env::Priority::TOTAL), |
636 | | file_read_latency_(num_levels), |
637 | | has_cf_change_since_dump_(true), |
638 | | bg_error_count_(0), |
639 | | number_levels_(num_levels), |
640 | | clock_(clock), |
641 | | cfd_(cfd), |
642 | 12.0k | started_at_(clock->NowMicros()) { |
643 | 12.0k | Cache* block_cache = GetBlockCacheForStats(); |
644 | 12.0k | if (block_cache) { |
645 | | // Extract or create stats collector. Could fail in rare cases. |
646 | 12.0k | Status s = CacheEntryStatsCollector<CacheEntryRoleStats>::GetShared( |
647 | 12.0k | block_cache, clock_, &cache_entry_stats_collector_); |
648 | 12.0k | if (s.ok()) { |
649 | 12.0k | assert(cache_entry_stats_collector_); |
650 | 12.0k | } else { |
651 | 0 | assert(!cache_entry_stats_collector_); |
652 | 0 | } |
653 | 12.0k | } |
654 | 12.0k | } |
655 | | |
656 | | void InternalStats::TEST_GetCacheEntryRoleStats(CacheEntryRoleStats* stats, |
657 | 0 | bool foreground) { |
658 | 0 | CollectCacheEntryStats(foreground); |
659 | 0 | if (cache_entry_stats_collector_) { |
660 | 0 | cache_entry_stats_collector_->GetStats(stats); |
661 | 0 | } |
662 | 0 | } |
663 | | |
664 | 60 | void InternalStats::CollectCacheEntryStats(bool foreground) { |
665 | | // This function is safe to call from any thread because |
666 | | // cache_entry_stats_collector_ field is const after constructor |
667 | | // and ->GetStats does its own synchronization, which also suffices for |
668 | | // cache_entry_stats_. |
669 | | |
670 | 60 | if (!cache_entry_stats_collector_) { |
671 | 0 | return; // nothing to do (e.g. no block cache) |
672 | 0 | } |
673 | | |
674 | | // For "background" collections, strictly cap the collection time by |
675 | | // expanding effective cache TTL. For foreground, be more aggressive about |
676 | | // getting latest data. |
677 | 60 | int min_interval_seconds = foreground ? 10 : 180; |
678 | | // 1/500 = max of 0.2% of one CPU thread |
679 | 60 | int min_interval_factor = foreground ? 10 : 500; |
680 | 60 | cache_entry_stats_collector_->CollectStats(min_interval_seconds, |
681 | 60 | min_interval_factor); |
682 | 60 | } |
683 | | |
684 | | std::function<void(const Slice& key, Cache::ObjectPtr value, size_t charge, |
685 | | const Cache::CacheItemHelper* helper)> |
686 | 60 | InternalStats::CacheEntryRoleStats::GetEntryCallback() { |
687 | 60 | return [&](const Slice& /*key*/, Cache::ObjectPtr /*value*/, size_t charge, |
688 | 73 | const Cache::CacheItemHelper* helper) -> void { |
689 | 73 | size_t role_idx = |
690 | 73 | static_cast<size_t>(helper ? helper->role : CacheEntryRole::kMisc); |
691 | 73 | entry_counts[role_idx]++; |
692 | 73 | total_charges[role_idx] += charge; |
693 | 73 | }; |
694 | 60 | } |
695 | | |
696 | | void InternalStats::CacheEntryRoleStats::BeginCollection( |
697 | 60 | Cache* cache, SystemClock*, uint64_t start_time_micros) { |
698 | 60 | Clear(); |
699 | 60 | last_start_time_micros_ = start_time_micros; |
700 | 60 | ++collection_count; |
701 | 60 | std::ostringstream str; |
702 | 60 | str << cache->Name() << "@" << static_cast<void*>(cache) << "#" |
703 | 60 | << port::GetProcessID(); |
704 | 60 | cache_id = str.str(); |
705 | 60 | cache_capacity = cache->GetCapacity(); |
706 | 60 | cache_usage = cache->GetUsage(); |
707 | 60 | table_size = cache->GetTableAddressCount(); |
708 | 60 | occupancy = cache->GetOccupancyCount(); |
709 | 60 | hash_seed = cache->GetHashSeed(); |
710 | 60 | } |
711 | | |
712 | | void InternalStats::CacheEntryRoleStats::EndCollection( |
713 | 60 | Cache*, SystemClock*, uint64_t end_time_micros) { |
714 | 60 | last_end_time_micros_ = end_time_micros; |
715 | 60 | } |
716 | | |
717 | 0 | void InternalStats::CacheEntryRoleStats::SkippedCollection() { |
718 | 0 | ++copies_of_last_collection; |
719 | 0 | } |
720 | | |
721 | 60 | uint64_t InternalStats::CacheEntryRoleStats::GetLastDurationMicros() const { |
722 | 60 | if (last_end_time_micros_ > last_start_time_micros_) { |
723 | 60 | return last_end_time_micros_ - last_start_time_micros_; |
724 | 60 | } else { |
725 | 0 | return 0U; |
726 | 0 | } |
727 | 60 | } |
728 | | |
729 | | std::string InternalStats::CacheEntryRoleStats::ToString( |
730 | 60 | SystemClock* clock) const { |
731 | 60 | std::ostringstream str; |
732 | 60 | str << "Block cache " << cache_id |
733 | 60 | << " capacity: " << BytesToHumanString(cache_capacity) |
734 | 60 | << " seed: " << hash_seed << " usage: " << BytesToHumanString(cache_usage) |
735 | 60 | << " table_size: " << table_size << " occupancy: " << occupancy |
736 | 60 | << " collections: " << collection_count |
737 | 60 | << " last_copies: " << copies_of_last_collection |
738 | 60 | << " last_secs: " << (GetLastDurationMicros() / 1000000.0) |
739 | 60 | << " secs_since: " |
740 | 60 | << ((clock->NowMicros() - last_end_time_micros_) / 1000000U) << "\n"; |
741 | 60 | str << "Block cache entry stats(count,size,portion):"; |
742 | 900 | for (size_t i = 0; i < kNumCacheEntryRoles; ++i) { |
743 | 840 | if (entry_counts[i] > 0) { |
744 | 63 | str << " " << kCacheEntryRoleToCamelString[i] << "(" << entry_counts[i] |
745 | 63 | << "," << BytesToHumanString(total_charges[i]) << "," |
746 | 63 | << (100.0 * total_charges[i] / cache_capacity) << "%)"; |
747 | 63 | } |
748 | 840 | } |
749 | 60 | str << "\n"; |
750 | 60 | return str.str(); |
751 | 60 | } |
752 | | |
753 | | void InternalStats::CacheEntryRoleStats::ToMap( |
754 | 0 | std::map<std::string, std::string>* values, SystemClock* clock) const { |
755 | 0 | values->clear(); |
756 | 0 | auto& v = *values; |
757 | 0 | v[BlockCacheEntryStatsMapKeys::CacheId()] = cache_id; |
758 | 0 | v[BlockCacheEntryStatsMapKeys::CacheCapacityBytes()] = |
759 | 0 | std::to_string(cache_capacity); |
760 | 0 | v[BlockCacheEntryStatsMapKeys::LastCollectionDurationSeconds()] = |
761 | 0 | std::to_string(GetLastDurationMicros() / 1000000.0); |
762 | 0 | v[BlockCacheEntryStatsMapKeys::LastCollectionAgeSeconds()] = |
763 | 0 | std::to_string((clock->NowMicros() - last_end_time_micros_) / 1000000U); |
764 | 0 | for (size_t i = 0; i < kNumCacheEntryRoles; ++i) { |
765 | 0 | auto role = static_cast<CacheEntryRole>(i); |
766 | 0 | v[BlockCacheEntryStatsMapKeys::EntryCount(role)] = |
767 | 0 | std::to_string(entry_counts[i]); |
768 | 0 | v[BlockCacheEntryStatsMapKeys::UsedBytes(role)] = |
769 | 0 | std::to_string(total_charges[i]); |
770 | 0 | v[BlockCacheEntryStatsMapKeys::UsedPercent(role)] = |
771 | 0 | std::to_string(100.0 * total_charges[i] / cache_capacity); |
772 | 0 | } |
773 | 0 | } |
774 | | |
775 | | bool InternalStats::HandleBlockCacheEntryStatsInternal(std::string* value, |
776 | 0 | bool fast) { |
777 | 0 | if (!cache_entry_stats_collector_) { |
778 | 0 | return false; |
779 | 0 | } |
780 | 0 | CollectCacheEntryStats(!fast /* foreground */); |
781 | 0 | CacheEntryRoleStats stats; |
782 | 0 | cache_entry_stats_collector_->GetStats(&stats); |
783 | 0 | *value = stats.ToString(clock_); |
784 | 0 | return true; |
785 | 0 | } |
786 | | |
787 | | bool InternalStats::HandleBlockCacheEntryStatsMapInternal( |
788 | 0 | std::map<std::string, std::string>* values, bool fast) { |
789 | 0 | if (!cache_entry_stats_collector_) { |
790 | 0 | return false; |
791 | 0 | } |
792 | 0 | CollectCacheEntryStats(!fast /* foreground */); |
793 | 0 | CacheEntryRoleStats stats; |
794 | 0 | cache_entry_stats_collector_->GetStats(&stats); |
795 | 0 | stats.ToMap(values, clock_); |
796 | 0 | return true; |
797 | 0 | } |
798 | | |
799 | | bool InternalStats::HandleBlockCacheEntryStats(std::string* value, |
800 | 0 | Slice /*suffix*/) { |
801 | 0 | return HandleBlockCacheEntryStatsInternal(value, false /* fast */); |
802 | 0 | } |
803 | | |
804 | | bool InternalStats::HandleBlockCacheEntryStatsMap( |
805 | 0 | std::map<std::string, std::string>* values, Slice /*suffix*/) { |
806 | 0 | return HandleBlockCacheEntryStatsMapInternal(values, false /* fast */); |
807 | 0 | } |
808 | | |
809 | | bool InternalStats::HandleFastBlockCacheEntryStats(std::string* value, |
810 | 0 | Slice /*suffix*/) { |
811 | 0 | return HandleBlockCacheEntryStatsInternal(value, true /* fast */); |
812 | 0 | } |
813 | | |
814 | | bool InternalStats::HandleFastBlockCacheEntryStatsMap( |
815 | 0 | std::map<std::string, std::string>* values, Slice /*suffix*/) { |
816 | 0 | return HandleBlockCacheEntryStatsMapInternal(values, true /* fast */); |
817 | 0 | } |
818 | | |
819 | | bool InternalStats::HandleLiveSstFilesSizeAtTemperature(std::string* value, |
820 | 0 | Slice suffix) { |
821 | 0 | uint64_t temperature; |
822 | 0 | bool ok = ConsumeDecimalNumber(&suffix, &temperature) && suffix.empty(); |
823 | 0 | if (!ok) { |
824 | 0 | return false; |
825 | 0 | } |
826 | | |
827 | 0 | uint64_t size = 0; |
828 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
829 | 0 | for (int level = 0; level < vstorage->num_levels(); level++) { |
830 | 0 | for (const auto& file_meta : vstorage->LevelFiles(level)) { |
831 | 0 | if (static_cast<uint8_t>(file_meta->temperature) == temperature) { |
832 | 0 | size += file_meta->fd.GetFileSize(); |
833 | 0 | } |
834 | 0 | } |
835 | 0 | } |
836 | |
|
837 | 0 | *value = std::to_string(size); |
838 | 0 | return true; |
839 | 0 | } |
840 | | |
841 | | bool InternalStats::HandleNumBlobFiles(uint64_t* value, DBImpl* /*db*/, |
842 | 0 | Version* /*version*/) { |
843 | 0 | assert(value); |
844 | 0 | assert(cfd_); |
845 | |
|
846 | 0 | const auto* current = cfd_->current(); |
847 | 0 | assert(current); |
848 | |
|
849 | 0 | const auto* vstorage = current->storage_info(); |
850 | 0 | assert(vstorage); |
851 | |
|
852 | 0 | const auto& blob_files = vstorage->GetBlobFiles(); |
853 | |
|
854 | 0 | *value = blob_files.size(); |
855 | |
|
856 | 0 | return true; |
857 | 0 | } |
858 | | |
859 | 0 | bool InternalStats::HandleBlobStats(std::string* value, Slice /*suffix*/) { |
860 | 0 | assert(value); |
861 | 0 | assert(cfd_); |
862 | |
|
863 | 0 | const auto* current = cfd_->current(); |
864 | 0 | assert(current); |
865 | |
|
866 | 0 | const auto* vstorage = current->storage_info(); |
867 | 0 | assert(vstorage); |
868 | |
|
869 | 0 | const auto blob_st = vstorage->GetBlobStats(); |
870 | |
|
871 | 0 | std::ostringstream oss; |
872 | |
|
873 | 0 | oss << "Number of blob files: " << vstorage->GetBlobFiles().size() |
874 | 0 | << "\nTotal size of blob files: " << blob_st.total_file_size |
875 | 0 | << "\nTotal size of garbage in blob files: " << blob_st.total_garbage_size |
876 | 0 | << "\nBlob file space amplification: " << blob_st.space_amp << '\n'; |
877 | |
|
878 | 0 | value->append(oss.str()); |
879 | |
|
880 | 0 | return true; |
881 | 0 | } |
882 | | |
883 | | bool InternalStats::HandleTotalBlobFileSize(uint64_t* value, DBImpl* /*db*/, |
884 | 0 | Version* /*version*/) { |
885 | 0 | assert(value); |
886 | 0 | assert(cfd_); |
887 | |
|
888 | 0 | *value = cfd_->GetTotalBlobFileSize(); |
889 | |
|
890 | 0 | return true; |
891 | 0 | } |
892 | | |
893 | | bool InternalStats::HandleLiveBlobFileSize(uint64_t* value, DBImpl* /*db*/, |
894 | 0 | Version* /*version*/) { |
895 | 0 | assert(value); |
896 | 0 | assert(cfd_); |
897 | |
|
898 | 0 | const auto* current = cfd_->current(); |
899 | 0 | assert(current); |
900 | |
|
901 | 0 | const auto* vstorage = current->storage_info(); |
902 | 0 | assert(vstorage); |
903 | |
|
904 | 0 | *value = vstorage->GetBlobStats().total_file_size; |
905 | |
|
906 | 0 | return true; |
907 | 0 | } |
908 | | |
909 | | bool InternalStats::HandleLiveBlobFileGarbageSize(uint64_t* value, |
910 | | DBImpl* /*db*/, |
911 | 0 | Version* /*version*/) { |
912 | 0 | assert(value); |
913 | 0 | assert(cfd_); |
914 | |
|
915 | 0 | const auto* current = cfd_->current(); |
916 | 0 | assert(current); |
917 | |
|
918 | 0 | const auto* vstorage = current->storage_info(); |
919 | 0 | assert(vstorage); |
920 | |
|
921 | 0 | *value = vstorage->GetBlobStats().total_garbage_size; |
922 | |
|
923 | 0 | return true; |
924 | 0 | } |
925 | | |
926 | 0 | Cache* InternalStats::GetBlobCacheForStats() { |
927 | 0 | return cfd_->ioptions()->blob_cache.get(); |
928 | 0 | } |
929 | | |
930 | | bool InternalStats::HandleBlobCacheCapacity(uint64_t* value, DBImpl* /*db*/, |
931 | 0 | Version* /*version*/) { |
932 | 0 | Cache* blob_cache = GetBlobCacheForStats(); |
933 | 0 | if (blob_cache) { |
934 | 0 | *value = static_cast<uint64_t>(blob_cache->GetCapacity()); |
935 | 0 | return true; |
936 | 0 | } |
937 | 0 | return false; |
938 | 0 | } |
939 | | |
940 | | bool InternalStats::HandleBlobCacheUsage(uint64_t* value, DBImpl* /*db*/, |
941 | 0 | Version* /*version*/) { |
942 | 0 | Cache* blob_cache = GetBlobCacheForStats(); |
943 | 0 | if (blob_cache) { |
944 | 0 | *value = static_cast<uint64_t>(blob_cache->GetUsage()); |
945 | 0 | return true; |
946 | 0 | } |
947 | 0 | return false; |
948 | 0 | } |
949 | | |
950 | | bool InternalStats::HandleBlobCachePinnedUsage(uint64_t* value, DBImpl* /*db*/, |
951 | 0 | Version* /*version*/) { |
952 | 0 | Cache* blob_cache = GetBlobCacheForStats(); |
953 | 0 | if (blob_cache) { |
954 | 0 | *value = static_cast<uint64_t>(blob_cache->GetPinnedUsage()); |
955 | 0 | return true; |
956 | 0 | } |
957 | 0 | return false; |
958 | 0 | } |
959 | | |
960 | 381 | const DBPropertyInfo* GetPropertyInfo(const Slice& property) { |
961 | 381 | std::string ppt_name = GetPropertyNameAndArg(property).first.ToString(); |
962 | 381 | auto ppt_info_iter = InternalStats::ppt_name_to_info.find(ppt_name); |
963 | 381 | if (ppt_info_iter == InternalStats::ppt_name_to_info.end()) { |
964 | 267 | return nullptr; |
965 | 267 | } |
966 | 114 | return &ppt_info_iter->second; |
967 | 381 | } |
968 | | |
969 | | bool InternalStats::GetStringProperty(const DBPropertyInfo& property_info, |
970 | | const Slice& property, |
971 | 117 | std::string* value) { |
972 | 117 | assert(value != nullptr); |
973 | 117 | assert(property_info.handle_string != nullptr); |
974 | 117 | Slice arg = GetPropertyNameAndArg(property).second; |
975 | 117 | return (this->*(property_info.handle_string))(value, arg); |
976 | 117 | } |
977 | | |
978 | | bool InternalStats::GetMapProperty(const DBPropertyInfo& property_info, |
979 | | const Slice& property, |
980 | 0 | std::map<std::string, std::string>* value) { |
981 | 0 | assert(value != nullptr); |
982 | 0 | assert(property_info.handle_map != nullptr); |
983 | 0 | Slice arg = GetPropertyNameAndArg(property).second; |
984 | 0 | return (this->*(property_info.handle_map))(value, arg); |
985 | 0 | } |
986 | | |
987 | | bool InternalStats::GetIntProperty(const DBPropertyInfo& property_info, |
988 | 0 | uint64_t* value, DBImpl* db) { |
989 | 0 | assert(value != nullptr); |
990 | 0 | assert(property_info.handle_int != nullptr && |
991 | 0 | !property_info.need_out_of_mutex); |
992 | 0 | db->mutex_.AssertHeld(); |
993 | 0 | return (this->*(property_info.handle_int))(value, db, nullptr /* version */); |
994 | 0 | } |
995 | | |
996 | | bool InternalStats::GetIntPropertyOutOfMutex( |
997 | 0 | const DBPropertyInfo& property_info, Version* version, uint64_t* value) { |
998 | 0 | assert(value != nullptr); |
999 | 0 | assert(property_info.handle_int != nullptr && |
1000 | 0 | property_info.need_out_of_mutex); |
1001 | 0 | return (this->*(property_info.handle_int))(value, nullptr /* db */, version); |
1002 | 0 | } |
1003 | | |
1004 | 0 | bool InternalStats::HandleNumFilesAtLevel(std::string* value, Slice suffix) { |
1005 | 0 | uint64_t level; |
1006 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1007 | 0 | bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty(); |
1008 | 0 | if (!ok || static_cast<int>(level) >= number_levels_) { |
1009 | 0 | return false; |
1010 | 0 | } else { |
1011 | 0 | char buf[100]; |
1012 | 0 | snprintf(buf, sizeof(buf), "%d", |
1013 | 0 | vstorage->NumLevelFiles(static_cast<int>(level))); |
1014 | 0 | *value = buf; |
1015 | 0 | return true; |
1016 | 0 | } |
1017 | 0 | } |
1018 | | |
1019 | | bool InternalStats::HandleCompressionRatioAtLevelPrefix(std::string* value, |
1020 | 0 | Slice suffix) { |
1021 | 0 | uint64_t level; |
1022 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1023 | 0 | bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty(); |
1024 | 0 | if (!ok || level >= static_cast<uint64_t>(number_levels_)) { |
1025 | 0 | return false; |
1026 | 0 | } |
1027 | 0 | *value = std::to_string( |
1028 | 0 | vstorage->GetEstimatedCompressionRatioAtLevel(static_cast<int>(level))); |
1029 | 0 | return true; |
1030 | 0 | } |
1031 | | |
1032 | 0 | bool InternalStats::HandleLevelStats(std::string* value, Slice /*suffix*/) { |
1033 | 0 | char buf[1000]; |
1034 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1035 | 0 | snprintf(buf, sizeof(buf), |
1036 | 0 | "Level Files Size(MB)\n" |
1037 | 0 | "--------------------\n"); |
1038 | 0 | value->append(buf); |
1039 | |
|
1040 | 0 | for (int level = 0; level < number_levels_; level++) { |
1041 | 0 | snprintf(buf, sizeof(buf), "%3d %8d %8.0f\n", level, |
1042 | 0 | vstorage->NumLevelFiles(level), |
1043 | 0 | vstorage->NumLevelBytes(level) / kMB); |
1044 | 0 | value->append(buf); |
1045 | 0 | } |
1046 | 0 | return true; |
1047 | 0 | } |
1048 | | |
1049 | 0 | bool InternalStats::HandleStats(std::string* value, Slice suffix) { |
1050 | 0 | if (!HandleCFStats(value, suffix)) { |
1051 | 0 | return false; |
1052 | 0 | } |
1053 | 0 | if (!HandleDBStats(value, suffix)) { |
1054 | 0 | return false; |
1055 | 0 | } |
1056 | 0 | return true; |
1057 | 0 | } |
1058 | | |
1059 | | bool InternalStats::HandleCFMapStats( |
1060 | 0 | std::map<std::string, std::string>* cf_stats, Slice /*suffix*/) { |
1061 | 0 | DumpCFMapStats(cf_stats); |
1062 | 0 | return true; |
1063 | 0 | } |
1064 | | |
1065 | 0 | bool InternalStats::HandleCFStats(std::string* value, Slice /*suffix*/) { |
1066 | 0 | DumpCFStats(value); |
1067 | 0 | return true; |
1068 | 0 | } |
1069 | | |
1070 | | bool InternalStats::HandleCFStatsPeriodic(std::string* value, |
1071 | 60 | Slice /*suffix*/) { |
1072 | 60 | bool has_change = has_cf_change_since_dump_; |
1073 | 60 | if (!has_change) { |
1074 | | // If file histogram changes, there is activity in this period too. |
1075 | 0 | uint64_t new_histogram_num = 0; |
1076 | 0 | for (int level = 0; level < number_levels_; level++) { |
1077 | 0 | new_histogram_num += file_read_latency_[level].num(); |
1078 | 0 | } |
1079 | 0 | new_histogram_num += blob_file_read_latency_.num(); |
1080 | 0 | if (new_histogram_num != last_histogram_num) { |
1081 | 0 | has_change = true; |
1082 | 0 | last_histogram_num = new_histogram_num; |
1083 | 0 | } |
1084 | 0 | } |
1085 | 60 | if (has_change) { |
1086 | 60 | no_cf_change_period_since_dump_ = 0; |
1087 | 60 | has_cf_change_since_dump_ = false; |
1088 | 60 | } else if (no_cf_change_period_since_dump_++ > 0) { |
1089 | | // Not ready to sync |
1090 | 0 | if (no_cf_change_period_since_dump_ == kMaxNoChangePeriodSinceDump) { |
1091 | | // Next periodic, we need to dump stats even if there is no change. |
1092 | 0 | no_cf_change_period_since_dump_ = 0; |
1093 | 0 | } |
1094 | 0 | return true; |
1095 | 0 | } |
1096 | | |
1097 | 60 | DumpCFStatsNoFileHistogram(/*is_periodic=*/true, value); |
1098 | 60 | DumpCFFileHistogram(value); |
1099 | 60 | return true; |
1100 | 60 | } |
1101 | | |
1102 | | bool InternalStats::HandleCFStatsNoFileHistogram(std::string* value, |
1103 | 0 | Slice /*suffix*/) { |
1104 | 0 | DumpCFStatsNoFileHistogram(/*is_periodic=*/false, value); |
1105 | 0 | return true; |
1106 | 0 | } |
1107 | | |
1108 | | bool InternalStats::HandleCFFileHistogram(std::string* value, |
1109 | 0 | Slice /*suffix*/) { |
1110 | 0 | DumpCFFileHistogram(value); |
1111 | 0 | return true; |
1112 | 0 | } |
1113 | | |
1114 | | bool InternalStats::HandleCFWriteStallStats(std::string* value, |
1115 | 0 | Slice /*suffix*/) { |
1116 | 0 | DumpCFStatsWriteStall(value); |
1117 | 0 | return true; |
1118 | 0 | } |
1119 | | |
1120 | | bool InternalStats::HandleCFWriteStallStatsMap( |
1121 | 0 | std::map<std::string, std::string>* value, Slice /*suffix*/) { |
1122 | 0 | DumpCFMapStatsWriteStall(value); |
1123 | 0 | return true; |
1124 | 0 | } |
1125 | | |
1126 | | bool InternalStats::HandleDBMapStats( |
1127 | 0 | std::map<std::string, std::string>* db_stats, Slice /*suffix*/) { |
1128 | 0 | DumpDBMapStats(db_stats); |
1129 | 0 | return true; |
1130 | 0 | } |
1131 | | |
1132 | 57 | bool InternalStats::HandleDBStats(std::string* value, Slice /*suffix*/) { |
1133 | 57 | DumpDBStats(value); |
1134 | 57 | return true; |
1135 | 57 | } |
1136 | | |
1137 | | bool InternalStats::HandleDBWriteStallStats(std::string* value, |
1138 | 0 | Slice /*suffix*/) { |
1139 | 0 | DumpDBStatsWriteStall(value); |
1140 | 0 | return true; |
1141 | 0 | } |
1142 | | |
1143 | | bool InternalStats::HandleDBWriteStallStatsMap( |
1144 | 0 | std::map<std::string, std::string>* value, Slice /*suffix*/) { |
1145 | 0 | DumpDBMapStatsWriteStall(value); |
1146 | 0 | return true; |
1147 | 0 | } |
1148 | | |
1149 | 0 | bool InternalStats::HandleSsTables(std::string* value, Slice /*suffix*/) { |
1150 | 0 | auto* current = cfd_->current(); |
1151 | 0 | *value = current->DebugString(true, true); |
1152 | 0 | return true; |
1153 | 0 | } |
1154 | | |
1155 | | bool InternalStats::HandleAggregatedTableProperties(std::string* value, |
1156 | 0 | Slice /*suffix*/) { |
1157 | 0 | std::shared_ptr<const TableProperties> tp; |
1158 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1159 | 0 | const ReadOptions read_options; |
1160 | 0 | auto s = cfd_->current()->GetAggregatedTableProperties(read_options, &tp); |
1161 | 0 | if (!s.ok()) { |
1162 | 0 | return false; |
1163 | 0 | } |
1164 | 0 | *value = tp->ToString(); |
1165 | 0 | return true; |
1166 | 0 | } |
1167 | | |
1168 | | static std::map<std::string, std::string> MapUint64ValuesToString( |
1169 | 0 | const std::map<std::string, uint64_t>& from) { |
1170 | 0 | std::map<std::string, std::string> to; |
1171 | 0 | for (const auto& e : from) { |
1172 | 0 | to[e.first] = std::to_string(e.second); |
1173 | 0 | } |
1174 | 0 | return to; |
1175 | 0 | } |
1176 | | |
1177 | | bool InternalStats::HandleAggregatedTablePropertiesMap( |
1178 | 0 | std::map<std::string, std::string>* values, Slice /*suffix*/) { |
1179 | 0 | std::shared_ptr<const TableProperties> tp; |
1180 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1181 | 0 | const ReadOptions read_options; |
1182 | 0 | auto s = cfd_->current()->GetAggregatedTableProperties(read_options, &tp); |
1183 | 0 | if (!s.ok()) { |
1184 | 0 | return false; |
1185 | 0 | } |
1186 | 0 | *values = MapUint64ValuesToString(tp->GetAggregatablePropertiesAsMap()); |
1187 | 0 | return true; |
1188 | 0 | } |
1189 | | |
1190 | | bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* values, |
1191 | 0 | Slice suffix) { |
1192 | 0 | uint64_t level; |
1193 | 0 | bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty(); |
1194 | 0 | if (!ok || static_cast<int>(level) >= number_levels_) { |
1195 | 0 | return false; |
1196 | 0 | } |
1197 | 0 | std::shared_ptr<const TableProperties> tp; |
1198 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1199 | 0 | const ReadOptions read_options; |
1200 | 0 | auto s = cfd_->current()->GetAggregatedTableProperties( |
1201 | 0 | read_options, &tp, static_cast<int>(level)); |
1202 | 0 | if (!s.ok()) { |
1203 | 0 | return false; |
1204 | 0 | } |
1205 | 0 | *values = tp->ToString(); |
1206 | 0 | return true; |
1207 | 0 | } |
1208 | | |
1209 | | bool InternalStats::HandleAggregatedTablePropertiesAtLevelMap( |
1210 | 0 | std::map<std::string, std::string>* values, Slice suffix) { |
1211 | 0 | uint64_t level; |
1212 | 0 | bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty(); |
1213 | 0 | if (!ok || static_cast<int>(level) >= number_levels_) { |
1214 | 0 | return false; |
1215 | 0 | } |
1216 | 0 | std::shared_ptr<const TableProperties> tp; |
1217 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1218 | 0 | const ReadOptions read_options; |
1219 | 0 | auto s = cfd_->current()->GetAggregatedTableProperties( |
1220 | 0 | read_options, &tp, static_cast<int>(level)); |
1221 | 0 | if (!s.ok()) { |
1222 | 0 | return false; |
1223 | 0 | } |
1224 | 0 | *values = MapUint64ValuesToString(tp->GetAggregatablePropertiesAsMap()); |
1225 | 0 | return true; |
1226 | 0 | } |
1227 | | |
1228 | | bool InternalStats::HandleNumImmutableMemTable(uint64_t* value, DBImpl* /*db*/, |
1229 | 0 | Version* /*version*/) { |
1230 | 0 | *value = cfd_->imm()->NumNotFlushed(); |
1231 | 0 | return true; |
1232 | 0 | } |
1233 | | |
1234 | | bool InternalStats::HandleNumImmutableMemTableFlushed(uint64_t* value, |
1235 | | DBImpl* /*db*/, |
1236 | 0 | Version* /*version*/) { |
1237 | 0 | *value = cfd_->imm()->NumFlushed(); |
1238 | 0 | return true; |
1239 | 0 | } |
1240 | | |
1241 | | bool InternalStats::HandleMemTableFlushPending(uint64_t* value, DBImpl* /*db*/, |
1242 | 0 | Version* /*version*/) { |
1243 | 0 | *value = (cfd_->imm()->IsFlushPending() ? 1 : 0); |
1244 | 0 | return true; |
1245 | 0 | } |
1246 | | |
1247 | | bool InternalStats::HandleNumRunningFlushes(uint64_t* value, DBImpl* db, |
1248 | 0 | Version* /*version*/) { |
1249 | 0 | *value = db->num_running_flushes(); |
1250 | 0 | return true; |
1251 | 0 | } |
1252 | | |
1253 | | bool InternalStats::HandleCompactionPending(uint64_t* value, DBImpl* /*db*/, |
1254 | 0 | Version* /*version*/) { |
1255 | | // 1 if the system already determines at least one compaction is needed. |
1256 | | // 0 otherwise, |
1257 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1258 | 0 | *value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0); |
1259 | 0 | return true; |
1260 | 0 | } |
1261 | | |
1262 | | bool InternalStats::HandleNumRunningCompactions(uint64_t* value, DBImpl* db, |
1263 | 0 | Version* /*version*/) { |
1264 | 0 | *value = db->num_running_compactions_; |
1265 | 0 | return true; |
1266 | 0 | } |
1267 | | |
1268 | | bool InternalStats::HandleBackgroundErrors(uint64_t* value, DBImpl* /*db*/, |
1269 | 0 | Version* /*version*/) { |
1270 | | // Accumulated number of errors in background flushes or compactions. |
1271 | 0 | *value = GetBackgroundErrorCount(); |
1272 | 0 | return true; |
1273 | 0 | } |
1274 | | |
1275 | | bool InternalStats::HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* /*db*/, |
1276 | 0 | Version* /*version*/) { |
1277 | | // Current size of the active memtable |
1278 | | // Using ApproximateMemoryUsageFast to avoid the need for synchronization |
1279 | 0 | *value = cfd_->mem()->ApproximateMemoryUsageFast(); |
1280 | 0 | return true; |
1281 | 0 | } |
1282 | | |
1283 | | bool InternalStats::HandleCurSizeAllMemTables(uint64_t* value, DBImpl* /*db*/, |
1284 | 0 | Version* /*version*/) { |
1285 | | // Current size of the active memtable + immutable memtables |
1286 | | // Using ApproximateMemoryUsageFast to avoid the need for synchronization |
1287 | 0 | *value = cfd_->mem()->ApproximateMemoryUsageFast() + |
1288 | 0 | cfd_->imm()->ApproximateUnflushedMemTablesMemoryUsage(); |
1289 | 0 | return true; |
1290 | 0 | } |
1291 | | |
1292 | | bool InternalStats::HandleSizeAllMemTables(uint64_t* value, DBImpl* /*db*/, |
1293 | 0 | Version* /*version*/) { |
1294 | | // Using ApproximateMemoryUsageFast to avoid the need for synchronization |
1295 | 0 | *value = cfd_->mem()->ApproximateMemoryUsageFast() + |
1296 | 0 | cfd_->imm()->ApproximateMemoryUsage(); |
1297 | 0 | return true; |
1298 | 0 | } |
1299 | | |
1300 | | bool InternalStats::HandleNumEntriesActiveMemTable(uint64_t* value, |
1301 | | DBImpl* /*db*/, |
1302 | 0 | Version* /*version*/) { |
1303 | | // Current number of entires in the active memtable |
1304 | 0 | *value = cfd_->mem()->num_entries(); |
1305 | 0 | return true; |
1306 | 0 | } |
1307 | | |
1308 | | bool InternalStats::HandleNumEntriesImmMemTables(uint64_t* value, |
1309 | | DBImpl* /*db*/, |
1310 | 0 | Version* /*version*/) { |
1311 | | // Current number of entries in the immutable memtables |
1312 | 0 | *value = cfd_->imm()->current()->GetTotalNumEntries(); |
1313 | 0 | return true; |
1314 | 0 | } |
1315 | | |
1316 | | bool InternalStats::HandleNumDeletesActiveMemTable(uint64_t* value, |
1317 | | DBImpl* /*db*/, |
1318 | 0 | Version* /*version*/) { |
1319 | | // Current number of entires in the active memtable |
1320 | 0 | *value = cfd_->mem()->num_deletes(); |
1321 | 0 | return true; |
1322 | 0 | } |
1323 | | |
1324 | | bool InternalStats::HandleNumDeletesImmMemTables(uint64_t* value, |
1325 | | DBImpl* /*db*/, |
1326 | 0 | Version* /*version*/) { |
1327 | | // Current number of entries in the immutable memtables |
1328 | 0 | *value = cfd_->imm()->current()->GetTotalNumDeletes(); |
1329 | 0 | return true; |
1330 | 0 | } |
1331 | | |
1332 | | bool InternalStats::HandleEstimateNumKeys(uint64_t* value, DBImpl* /*db*/, |
1333 | 0 | Version* /*version*/) { |
1334 | | // Estimate number of entries in the column family: |
1335 | | // Use estimated entries in tables + total entries in memtables. |
1336 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1337 | 0 | uint64_t estimate_keys = cfd_->mem()->num_entries() + |
1338 | 0 | cfd_->imm()->current()->GetTotalNumEntries() + |
1339 | 0 | vstorage->GetEstimatedActiveKeys(); |
1340 | 0 | uint64_t estimate_deletes = |
1341 | 0 | cfd_->mem()->num_deletes() + cfd_->imm()->current()->GetTotalNumDeletes(); |
1342 | 0 | *value = estimate_keys > estimate_deletes * 2 |
1343 | 0 | ? estimate_keys - (estimate_deletes * 2) |
1344 | 0 | : 0; |
1345 | 0 | return true; |
1346 | 0 | } |
1347 | | |
1348 | | bool InternalStats::HandleNumSnapshots(uint64_t* value, DBImpl* db, |
1349 | 0 | Version* /*version*/) { |
1350 | 0 | *value = db->snapshots().count(); |
1351 | 0 | return true; |
1352 | 0 | } |
1353 | | |
1354 | | bool InternalStats::HandleOldestSnapshotTime(uint64_t* value, DBImpl* db, |
1355 | 0 | Version* /*version*/) { |
1356 | 0 | *value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotTime()); |
1357 | 0 | return true; |
1358 | 0 | } |
1359 | | |
1360 | | bool InternalStats::HandleOldestSnapshotSequence(uint64_t* value, DBImpl* db, |
1361 | 0 | Version* /*version*/) { |
1362 | 0 | *value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotSequence()); |
1363 | 0 | return true; |
1364 | 0 | } |
1365 | | |
1366 | | bool InternalStats::HandleNumLiveVersions(uint64_t* value, DBImpl* /*db*/, |
1367 | 0 | Version* /*version*/) { |
1368 | 0 | *value = cfd_->GetNumLiveVersions(); |
1369 | 0 | return true; |
1370 | 0 | } |
1371 | | |
1372 | | bool InternalStats::HandleCurrentSuperVersionNumber(uint64_t* value, |
1373 | | DBImpl* /*db*/, |
1374 | 0 | Version* /*version*/) { |
1375 | 0 | *value = cfd_->GetSuperVersionNumber(); |
1376 | 0 | return true; |
1377 | 0 | } |
1378 | | |
1379 | | bool InternalStats::HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db, |
1380 | 0 | Version* /*version*/) { |
1381 | 0 | *value = db->IsFileDeletionsEnabled() ? 1 : 0; |
1382 | 0 | return true; |
1383 | 0 | } |
1384 | | |
1385 | | bool InternalStats::HandleBaseLevel(uint64_t* value, DBImpl* /*db*/, |
1386 | 0 | Version* /*version*/) { |
1387 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1388 | 0 | *value = vstorage->base_level(); |
1389 | 0 | return true; |
1390 | 0 | } |
1391 | | |
1392 | | bool InternalStats::HandleTotalSstFilesSize(uint64_t* value, DBImpl* /*db*/, |
1393 | 0 | Version* /*version*/) { |
1394 | 0 | *value = cfd_->GetTotalSstFilesSize(); |
1395 | 0 | return true; |
1396 | 0 | } |
1397 | | |
1398 | | bool InternalStats::HandleLiveSstFilesSize(uint64_t* value, DBImpl* /*db*/, |
1399 | 0 | Version* /*version*/) { |
1400 | 0 | *value = cfd_->GetLiveSstFilesSize(); |
1401 | 0 | return true; |
1402 | 0 | } |
1403 | | |
1404 | | bool InternalStats::HandleObsoleteSstFilesSize(uint64_t* value, DBImpl* db, |
1405 | 0 | Version* /*version*/) { |
1406 | 0 | *value = db->GetObsoleteSstFilesSize(); |
1407 | 0 | return true; |
1408 | 0 | } |
1409 | | |
1410 | | bool InternalStats::HandleEstimatePendingCompactionBytes(uint64_t* value, |
1411 | | DBImpl* /*db*/, |
1412 | 0 | Version* /*version*/) { |
1413 | 0 | const auto* vstorage = cfd_->current()->storage_info(); |
1414 | 0 | *value = vstorage->estimated_compaction_needed_bytes(); |
1415 | 0 | return true; |
1416 | 0 | } |
1417 | | |
1418 | | bool InternalStats::HandleEstimateTableReadersMem(uint64_t* value, |
1419 | | DBImpl* /*db*/, |
1420 | 0 | Version* version) { |
1421 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1422 | 0 | const ReadOptions read_options; |
1423 | 0 | *value = (version == nullptr) |
1424 | 0 | ? 0 |
1425 | 0 | : version->GetMemoryUsageByTableReaders(read_options); |
1426 | 0 | return true; |
1427 | 0 | } |
1428 | | |
1429 | | bool InternalStats::HandleEstimateLiveDataSize(uint64_t* value, DBImpl* /*db*/, |
1430 | 0 | Version* version) { |
1431 | 0 | const auto* vstorage = version->storage_info(); |
1432 | 0 | *value = vstorage->EstimateLiveDataSize(); |
1433 | 0 | return true; |
1434 | 0 | } |
1435 | | |
1436 | | bool InternalStats::HandleMinLogNumberToKeep(uint64_t* value, DBImpl* db, |
1437 | 0 | Version* /*version*/) { |
1438 | 0 | *value = db->MinLogNumberToKeep(); |
1439 | 0 | return true; |
1440 | 0 | } |
1441 | | |
1442 | | bool InternalStats::HandleMinObsoleteSstNumberToKeep(uint64_t* value, |
1443 | | DBImpl* db, |
1444 | 0 | Version* /*version*/) { |
1445 | 0 | *value = db->MinObsoleteSstNumberToKeep(); |
1446 | 0 | return true; |
1447 | 0 | } |
1448 | | |
1449 | | bool InternalStats::HandleActualDelayedWriteRate(uint64_t* value, DBImpl* db, |
1450 | 0 | Version* /*version*/) { |
1451 | 0 | const WriteController& wc = db->write_controller(); |
1452 | 0 | if (!wc.NeedsDelay()) { |
1453 | 0 | *value = 0; |
1454 | 0 | } else { |
1455 | 0 | *value = wc.delayed_write_rate(); |
1456 | 0 | } |
1457 | 0 | return true; |
1458 | 0 | } |
1459 | | |
1460 | | bool InternalStats::HandleIsWriteStopped(uint64_t* value, DBImpl* db, |
1461 | 0 | Version* /*version*/) { |
1462 | 0 | *value = db->write_controller().IsStopped() ? 1 : 0; |
1463 | 0 | return true; |
1464 | 0 | } |
1465 | | |
1466 | | bool InternalStats::HandleEstimateOldestKeyTime(uint64_t* value, DBImpl* /*db*/, |
1467 | 0 | Version* /*version*/) { |
1468 | | // TODO(yiwu): The property is currently available for fifo compaction |
1469 | | // with allow_compaction = false. This is because we don't propagate |
1470 | | // oldest_key_time on compaction. |
1471 | 0 | if (cfd_->ioptions()->compaction_style != kCompactionStyleFIFO || |
1472 | 0 | cfd_->GetCurrentMutableCFOptions() |
1473 | 0 | ->compaction_options_fifo.allow_compaction) { |
1474 | 0 | return false; |
1475 | 0 | } |
1476 | | // TODO: plumb Env::IOActivity, Env::IOPriority |
1477 | 0 | const ReadOptions read_options; |
1478 | 0 | TablePropertiesCollection collection; |
1479 | 0 | auto s = cfd_->current()->GetPropertiesOfAllTables(read_options, &collection); |
1480 | 0 | if (!s.ok()) { |
1481 | 0 | return false; |
1482 | 0 | } |
1483 | 0 | *value = std::numeric_limits<uint64_t>::max(); |
1484 | 0 | for (auto& p : collection) { |
1485 | 0 | *value = std::min(*value, p.second->oldest_key_time); |
1486 | 0 | if (*value == 0) { |
1487 | 0 | break; |
1488 | 0 | } |
1489 | 0 | } |
1490 | 0 | if (*value > 0) { |
1491 | 0 | *value = std::min({cfd_->mem()->ApproximateOldestKeyTime(), |
1492 | 0 | cfd_->imm()->ApproximateOldestKeyTime(), *value}); |
1493 | 0 | } |
1494 | 0 | return *value > 0 && *value < std::numeric_limits<uint64_t>::max(); |
1495 | 0 | } |
1496 | | |
1497 | 12.0k | Cache* InternalStats::GetBlockCacheForStats() { |
1498 | 12.0k | auto* table_factory = cfd_->ioptions()->table_factory.get(); |
1499 | 12.0k | assert(table_factory != nullptr); |
1500 | 12.0k | return table_factory->GetOptions<Cache>(TableFactory::kBlockCacheOpts()); |
1501 | 12.0k | } |
1502 | | |
1503 | | bool InternalStats::HandleBlockCacheCapacity(uint64_t* value, DBImpl* /*db*/, |
1504 | 0 | Version* /*version*/) { |
1505 | 0 | Cache* block_cache = GetBlockCacheForStats(); |
1506 | 0 | if (block_cache) { |
1507 | 0 | *value = static_cast<uint64_t>(block_cache->GetCapacity()); |
1508 | 0 | return true; |
1509 | 0 | } |
1510 | 0 | return false; |
1511 | 0 | } |
1512 | | |
1513 | | bool InternalStats::HandleBlockCacheUsage(uint64_t* value, DBImpl* /*db*/, |
1514 | 0 | Version* /*version*/) { |
1515 | 0 | Cache* block_cache = GetBlockCacheForStats(); |
1516 | 0 | if (block_cache) { |
1517 | 0 | *value = static_cast<uint64_t>(block_cache->GetUsage()); |
1518 | 0 | return true; |
1519 | 0 | } |
1520 | 0 | return false; |
1521 | 0 | } |
1522 | | |
1523 | | bool InternalStats::HandleBlockCachePinnedUsage(uint64_t* value, DBImpl* /*db*/, |
1524 | 0 | Version* /*version*/) { |
1525 | 0 | Cache* block_cache = GetBlockCacheForStats(); |
1526 | 0 | if (block_cache) { |
1527 | 0 | *value = static_cast<uint64_t>(block_cache->GetPinnedUsage()); |
1528 | 0 | return true; |
1529 | 0 | } |
1530 | 0 | return false; |
1531 | 0 | } |
1532 | | |
1533 | | void InternalStats::DumpDBMapStats( |
1534 | 0 | std::map<std::string, std::string>* db_stats) { |
1535 | 0 | for (int i = 0; i < static_cast<int>(kIntStatsNumMax); ++i) { |
1536 | 0 | InternalDBStatsType type = static_cast<InternalDBStatsType>(i); |
1537 | 0 | (*db_stats)[db_stats_type_to_info.at(type).property_name] = |
1538 | 0 | std::to_string(GetDBStats(type)); |
1539 | 0 | } |
1540 | 0 | double seconds_up = (clock_->NowMicros() - started_at_) / kMicrosInSec; |
1541 | 0 | (*db_stats)["db.uptime"] = std::to_string(seconds_up); |
1542 | 0 | } |
1543 | | |
1544 | 57 | void InternalStats::DumpDBStats(std::string* value) { |
1545 | 57 | char buf[1000]; |
1546 | | // DB-level stats, only available from default column family |
1547 | 57 | double seconds_up = (clock_->NowMicros() - started_at_) / kMicrosInSec; |
1548 | 57 | double interval_seconds_up = seconds_up - db_stats_snapshot_.seconds_up; |
1549 | 57 | snprintf(buf, sizeof(buf), |
1550 | 57 | "\n** DB Stats **\nUptime(secs): %.1f total, %.1f interval\n", |
1551 | 57 | seconds_up, interval_seconds_up); |
1552 | 57 | value->append(buf); |
1553 | | // Cumulative |
1554 | 57 | uint64_t user_bytes_written = |
1555 | 57 | GetDBStats(InternalStats::kIntStatsBytesWritten); |
1556 | 57 | uint64_t num_keys_written = |
1557 | 57 | GetDBStats(InternalStats::kIntStatsNumKeysWritten); |
1558 | 57 | uint64_t write_other = GetDBStats(InternalStats::kIntStatsWriteDoneByOther); |
1559 | 57 | uint64_t write_self = GetDBStats(InternalStats::kIntStatsWriteDoneBySelf); |
1560 | 57 | uint64_t wal_bytes = GetDBStats(InternalStats::kIntStatsWalFileBytes); |
1561 | 57 | uint64_t wal_synced = GetDBStats(InternalStats::kIntStatsWalFileSynced); |
1562 | 57 | uint64_t write_with_wal = GetDBStats(InternalStats::kIntStatsWriteWithWal); |
1563 | 57 | uint64_t write_stall_micros = |
1564 | 57 | GetDBStats(InternalStats::kIntStatsWriteStallMicros); |
1565 | | |
1566 | 57 | const int kHumanMicrosLen = 32; |
1567 | 57 | char human_micros[kHumanMicrosLen]; |
1568 | | |
1569 | | // Data |
1570 | | // writes: total number of write requests. |
1571 | | // keys: total number of key updates issued by all the write requests |
1572 | | // commit groups: number of group commits issued to the DB. Each group can |
1573 | | // contain one or more writes. |
1574 | | // so writes/keys is the average number of put in multi-put or put |
1575 | | // writes/groups is the average group commit size. |
1576 | | // |
1577 | | // The format is the same for interval stats. |
1578 | 57 | snprintf(buf, sizeof(buf), |
1579 | 57 | "Cumulative writes: %s writes, %s keys, %s commit groups, " |
1580 | 57 | "%.1f writes per commit group, ingest: %.2f GB, %.2f MB/s\n", |
1581 | 57 | NumberToHumanString(write_other + write_self).c_str(), |
1582 | 57 | NumberToHumanString(num_keys_written).c_str(), |
1583 | 57 | NumberToHumanString(write_self).c_str(), |
1584 | 57 | (write_other + write_self) / |
1585 | 57 | std::max(1.0, static_cast<double>(write_self)), |
1586 | 57 | user_bytes_written / kGB, |
1587 | 57 | user_bytes_written / kMB / std::max(seconds_up, 0.001)); |
1588 | 57 | value->append(buf); |
1589 | | // WAL |
1590 | 57 | snprintf(buf, sizeof(buf), |
1591 | 57 | "Cumulative WAL: %s writes, %s syncs, " |
1592 | 57 | "%.2f writes per sync, written: %.2f GB, %.2f MB/s\n", |
1593 | 57 | NumberToHumanString(write_with_wal).c_str(), |
1594 | 57 | NumberToHumanString(wal_synced).c_str(), |
1595 | 57 | write_with_wal / std::max(1.0, static_cast<double>(wal_synced)), |
1596 | 57 | wal_bytes / kGB, wal_bytes / kMB / std::max(seconds_up, 0.001)); |
1597 | 57 | value->append(buf); |
1598 | | // Stall |
1599 | 57 | AppendHumanMicros(write_stall_micros, human_micros, kHumanMicrosLen, true); |
1600 | 57 | snprintf(buf, sizeof(buf), "Cumulative stall: %s, %.1f percent\n", |
1601 | 57 | human_micros, |
1602 | | // 10000 = divide by 1M to get secs, then multiply by 100 for pct |
1603 | 57 | write_stall_micros / 10000.0 / std::max(seconds_up, 0.001)); |
1604 | 57 | value->append(buf); |
1605 | | |
1606 | | // Interval |
1607 | 57 | uint64_t interval_write_other = write_other - db_stats_snapshot_.write_other; |
1608 | 57 | uint64_t interval_write_self = write_self - db_stats_snapshot_.write_self; |
1609 | 57 | uint64_t interval_num_keys_written = |
1610 | 57 | num_keys_written - db_stats_snapshot_.num_keys_written; |
1611 | 57 | snprintf( |
1612 | 57 | buf, sizeof(buf), |
1613 | 57 | "Interval writes: %s writes, %s keys, %s commit groups, " |
1614 | 57 | "%.1f writes per commit group, ingest: %.2f MB, %.2f MB/s\n", |
1615 | 57 | NumberToHumanString(interval_write_other + interval_write_self).c_str(), |
1616 | 57 | NumberToHumanString(interval_num_keys_written).c_str(), |
1617 | 57 | NumberToHumanString(interval_write_self).c_str(), |
1618 | 57 | static_cast<double>(interval_write_other + interval_write_self) / |
1619 | 57 | std::max(1.0, static_cast<double>(interval_write_self)), |
1620 | 57 | (user_bytes_written - db_stats_snapshot_.ingest_bytes) / kMB, |
1621 | 57 | (user_bytes_written - db_stats_snapshot_.ingest_bytes) / kMB / |
1622 | 57 | std::max(interval_seconds_up, 0.001)), |
1623 | 57 | value->append(buf); |
1624 | | |
1625 | 57 | uint64_t interval_write_with_wal = |
1626 | 57 | write_with_wal - db_stats_snapshot_.write_with_wal; |
1627 | 57 | uint64_t interval_wal_synced = wal_synced - db_stats_snapshot_.wal_synced; |
1628 | 57 | uint64_t interval_wal_bytes = wal_bytes - db_stats_snapshot_.wal_bytes; |
1629 | | |
1630 | 57 | snprintf(buf, sizeof(buf), |
1631 | 57 | "Interval WAL: %s writes, %s syncs, " |
1632 | 57 | "%.2f writes per sync, written: %.2f GB, %.2f MB/s\n", |
1633 | 57 | NumberToHumanString(interval_write_with_wal).c_str(), |
1634 | 57 | NumberToHumanString(interval_wal_synced).c_str(), |
1635 | 57 | interval_write_with_wal / |
1636 | 57 | std::max(1.0, static_cast<double>(interval_wal_synced)), |
1637 | 57 | interval_wal_bytes / kGB, |
1638 | 57 | interval_wal_bytes / kMB / std::max(interval_seconds_up, 0.001)); |
1639 | 57 | value->append(buf); |
1640 | | |
1641 | | // Stall |
1642 | 57 | AppendHumanMicros(write_stall_micros - db_stats_snapshot_.write_stall_micros, |
1643 | 57 | human_micros, kHumanMicrosLen, true); |
1644 | 57 | snprintf(buf, sizeof(buf), "Interval stall: %s, %.1f percent\n", human_micros, |
1645 | | // 10000 = divide by 1M to get secs, then multiply by 100 for pct |
1646 | 57 | (write_stall_micros - db_stats_snapshot_.write_stall_micros) / |
1647 | 57 | 10000.0 / std::max(interval_seconds_up, 0.001)); |
1648 | 57 | value->append(buf); |
1649 | | |
1650 | 57 | std::string write_stall_stats; |
1651 | 57 | DumpDBStatsWriteStall(&write_stall_stats); |
1652 | 57 | value->append(write_stall_stats); |
1653 | | |
1654 | 57 | db_stats_snapshot_.seconds_up = seconds_up; |
1655 | 57 | db_stats_snapshot_.ingest_bytes = user_bytes_written; |
1656 | 57 | db_stats_snapshot_.write_other = write_other; |
1657 | 57 | db_stats_snapshot_.write_self = write_self; |
1658 | 57 | db_stats_snapshot_.num_keys_written = num_keys_written; |
1659 | 57 | db_stats_snapshot_.wal_bytes = wal_bytes; |
1660 | 57 | db_stats_snapshot_.wal_synced = wal_synced; |
1661 | 57 | db_stats_snapshot_.write_with_wal = write_with_wal; |
1662 | 57 | db_stats_snapshot_.write_stall_micros = write_stall_micros; |
1663 | 57 | } |
1664 | | |
1665 | | void InternalStats::DumpDBMapStatsWriteStall( |
1666 | 57 | std::map<std::string, std::string>* value) { |
1667 | 57 | constexpr uint32_t max_db_scope_write_stall_cause = |
1668 | 57 | static_cast<uint32_t>(WriteStallCause::kDBScopeWriteStallCauseEnumMax); |
1669 | | |
1670 | 57 | for (uint32_t i = |
1671 | 57 | max_db_scope_write_stall_cause - kNumDBScopeWriteStallCauses; |
1672 | 114 | i < max_db_scope_write_stall_cause; ++i) { |
1673 | 57 | for (uint32_t j = 0; |
1674 | 171 | j < static_cast<uint32_t>(WriteStallCondition::kNormal); ++j) { |
1675 | 114 | WriteStallCause cause = static_cast<WriteStallCause>(i); |
1676 | 114 | WriteStallCondition condition = static_cast<WriteStallCondition>(j); |
1677 | 114 | InternalStats::InternalDBStatsType internal_db_stat = |
1678 | 114 | InternalDBStat(cause, condition); |
1679 | | |
1680 | 114 | if (internal_db_stat == InternalStats::kIntStatsNumMax) { |
1681 | 57 | continue; |
1682 | 57 | } |
1683 | | |
1684 | 57 | std::string name = |
1685 | 57 | WriteStallStatsMapKeys::CauseConditionCount(cause, condition); |
1686 | 57 | uint64_t stat = |
1687 | 57 | db_stats_[static_cast<std::size_t>(internal_db_stat)].load( |
1688 | 57 | std::memory_order_relaxed); |
1689 | 57 | (*value)[name] = std::to_string(stat); |
1690 | 57 | } |
1691 | 57 | } |
1692 | 57 | } |
1693 | | |
1694 | 57 | void InternalStats::DumpDBStatsWriteStall(std::string* value) { |
1695 | 57 | assert(value); |
1696 | | |
1697 | 57 | std::map<std::string, std::string> write_stall_stats_map; |
1698 | 57 | DumpDBMapStatsWriteStall(&write_stall_stats_map); |
1699 | | |
1700 | 57 | std::ostringstream str; |
1701 | 57 | str << "Write Stall (count): "; |
1702 | | |
1703 | 57 | for (auto write_stall_stats_map_iter = write_stall_stats_map.begin(); |
1704 | 114 | write_stall_stats_map_iter != write_stall_stats_map.end(); |
1705 | 57 | write_stall_stats_map_iter++) { |
1706 | 57 | const auto& name_and_stat = *write_stall_stats_map_iter; |
1707 | 57 | str << name_and_stat.first << ": " << name_and_stat.second; |
1708 | 57 | if (std::next(write_stall_stats_map_iter) == write_stall_stats_map.end()) { |
1709 | 57 | str << "\n"; |
1710 | 57 | } else { |
1711 | 0 | str << ", "; |
1712 | 0 | } |
1713 | 57 | } |
1714 | 57 | *value = str.str(); |
1715 | 57 | } |
1716 | | |
1717 | | /** |
1718 | | * Dump Compaction Level stats to a map of stat name with "compaction." prefix |
1719 | | * to value in double as string. The level in stat name is represented with |
1720 | | * a prefix "Lx" where "x" is the level number. A special level "Sum" |
1721 | | * represents the sum of a stat for all levels. |
1722 | | * The result also contains IO stall counters which keys start with "io_stalls." |
1723 | | * and values represent uint64 encoded as strings. |
1724 | | */ |
1725 | | void InternalStats::DumpCFMapStats( |
1726 | 0 | std::map<std::string, std::string>* cf_stats) { |
1727 | 0 | const VersionStorageInfo* vstorage = cfd_->current()->storage_info(); |
1728 | 0 | CompactionStats compaction_stats_sum; |
1729 | 0 | std::map<int, std::map<LevelStatType, double>> levels_stats; |
1730 | 0 | DumpCFMapStats(vstorage, &levels_stats, &compaction_stats_sum); |
1731 | 0 | for (auto const& level_ent : levels_stats) { |
1732 | 0 | auto level_str = |
1733 | 0 | level_ent.first == -1 ? "Sum" : "L" + std::to_string(level_ent.first); |
1734 | 0 | for (auto const& stat_ent : level_ent.second) { |
1735 | 0 | auto stat_type = stat_ent.first; |
1736 | 0 | auto key_str = |
1737 | 0 | "compaction." + level_str + "." + |
1738 | 0 | InternalStats::compaction_level_stats.at(stat_type).property_name; |
1739 | 0 | (*cf_stats)[key_str] = std::to_string(stat_ent.second); |
1740 | 0 | } |
1741 | 0 | } |
1742 | |
|
1743 | 0 | DumpCFMapStatsWriteStall(cf_stats); |
1744 | 0 | } |
1745 | | |
1746 | | void InternalStats::DumpCFMapStats( |
1747 | | const VersionStorageInfo* vstorage, |
1748 | | std::map<int, std::map<LevelStatType, double>>* levels_stats, |
1749 | 60 | CompactionStats* compaction_stats_sum) { |
1750 | 60 | assert(vstorage); |
1751 | | |
1752 | 60 | int num_levels_to_check = |
1753 | 60 | (cfd_->ioptions()->compaction_style == kCompactionStyleLevel) |
1754 | 60 | ? vstorage->num_levels() - 1 |
1755 | 60 | : 1; |
1756 | | |
1757 | | // Compaction scores are sorted based on its value. Restore them to the |
1758 | | // level order |
1759 | 60 | std::vector<double> compaction_score(number_levels_, 0); |
1760 | 420 | for (int i = 0; i < num_levels_to_check; ++i) { |
1761 | 360 | compaction_score[vstorage->CompactionScoreLevel(i)] = |
1762 | 360 | vstorage->CompactionScore(i); |
1763 | 360 | } |
1764 | | // Count # of files being compacted for each level |
1765 | 60 | std::vector<int> files_being_compacted(number_levels_, 0); |
1766 | 480 | for (int level = 0; level < number_levels_; ++level) { |
1767 | 420 | for (auto* f : vstorage->LevelFiles(level)) { |
1768 | 13 | if (f->being_compacted) { |
1769 | 5 | ++files_being_compacted[level]; |
1770 | 5 | } |
1771 | 13 | } |
1772 | 420 | } |
1773 | | |
1774 | 60 | int total_files = 0; |
1775 | 60 | int total_files_being_compacted = 0; |
1776 | 60 | double total_file_size = 0; |
1777 | 60 | uint64_t flush_ingest = cf_stats_value_[BYTES_FLUSHED]; |
1778 | 60 | uint64_t add_file_ingest = cf_stats_value_[BYTES_INGESTED_ADD_FILE]; |
1779 | 60 | uint64_t curr_ingest = flush_ingest + add_file_ingest; |
1780 | 480 | for (int level = 0; level < number_levels_; level++) { |
1781 | 420 | int files = vstorage->NumLevelFiles(level); |
1782 | 420 | total_files += files; |
1783 | 420 | total_files_being_compacted += files_being_compacted[level]; |
1784 | 420 | if (comp_stats_[level].micros > 0 || comp_stats_[level].cpu_micros > 0 || |
1785 | 420 | files > 0) { |
1786 | 8 | compaction_stats_sum->Add(comp_stats_[level]); |
1787 | 8 | total_file_size += vstorage->NumLevelBytes(level); |
1788 | 8 | uint64_t input_bytes; |
1789 | 8 | if (level == 0) { |
1790 | 3 | input_bytes = curr_ingest; |
1791 | 5 | } else { |
1792 | 5 | input_bytes = comp_stats_[level].bytes_read_non_output_levels + |
1793 | 5 | comp_stats_[level].bytes_read_blob; |
1794 | 5 | } |
1795 | 8 | double w_amp = |
1796 | 8 | (input_bytes == 0) |
1797 | 8 | ? 0.0 |
1798 | 8 | : static_cast<double>(comp_stats_[level].bytes_written + |
1799 | 2 | comp_stats_[level].bytes_written_blob) / |
1800 | 2 | input_bytes; |
1801 | 8 | std::map<LevelStatType, double> level_stats; |
1802 | 8 | PrepareLevelStats(&level_stats, files, files_being_compacted[level], |
1803 | 8 | static_cast<double>(vstorage->NumLevelBytes(level)), |
1804 | 8 | compaction_score[level], w_amp, comp_stats_[level]); |
1805 | 8 | (*levels_stats)[level] = level_stats; |
1806 | 8 | } |
1807 | 420 | } |
1808 | | // Cumulative summary |
1809 | 60 | double w_amp = (0 == curr_ingest) |
1810 | 60 | ? 0.0 |
1811 | 60 | : (compaction_stats_sum->bytes_written + |
1812 | 2 | compaction_stats_sum->bytes_written_blob) / |
1813 | 2 | static_cast<double>(curr_ingest); |
1814 | | // Stats summary across levels |
1815 | 60 | std::map<LevelStatType, double> sum_stats; |
1816 | 60 | PrepareLevelStats(&sum_stats, total_files, total_files_being_compacted, |
1817 | 60 | total_file_size, 0, w_amp, *compaction_stats_sum); |
1818 | 60 | (*levels_stats)[-1] = sum_stats; // -1 is for the Sum level |
1819 | 60 | } |
1820 | | |
1821 | | void InternalStats::DumpCFMapStatsByPriority( |
1822 | 60 | std::map<int, std::map<LevelStatType, double>>* priorities_stats) { |
1823 | 300 | for (size_t priority = 0; priority < comp_stats_by_pri_.size(); priority++) { |
1824 | 240 | if (comp_stats_by_pri_[priority].micros > 0) { |
1825 | 2 | std::map<LevelStatType, double> priority_stats; |
1826 | 2 | PrepareLevelStats(&priority_stats, 0 /* num_files */, |
1827 | 2 | 0 /* being_compacted */, 0 /* total_file_size */, |
1828 | 2 | 0 /* compaction_score */, 0 /* w_amp */, |
1829 | 2 | comp_stats_by_pri_[priority]); |
1830 | 2 | (*priorities_stats)[static_cast<int>(priority)] = priority_stats; |
1831 | 2 | } |
1832 | 240 | } |
1833 | 60 | } |
1834 | | |
1835 | | void InternalStats::DumpCFMapStatsWriteStall( |
1836 | 60 | std::map<std::string, std::string>* value) { |
1837 | 60 | uint64_t total_delays = 0; |
1838 | 60 | uint64_t total_stops = 0; |
1839 | 60 | constexpr uint32_t max_cf_scope_write_stall_cause = |
1840 | 60 | static_cast<uint32_t>(WriteStallCause::kCFScopeWriteStallCauseEnumMax); |
1841 | | |
1842 | 60 | for (uint32_t i = |
1843 | 60 | max_cf_scope_write_stall_cause - kNumCFScopeWriteStallCauses; |
1844 | 240 | i < max_cf_scope_write_stall_cause; ++i) { |
1845 | 180 | for (uint32_t j = 0; |
1846 | 540 | j < static_cast<uint32_t>(WriteStallCondition::kNormal); ++j) { |
1847 | 360 | WriteStallCause cause = static_cast<WriteStallCause>(i); |
1848 | 360 | WriteStallCondition condition = static_cast<WriteStallCondition>(j); |
1849 | 360 | InternalStats::InternalCFStatsType internal_cf_stat = |
1850 | 360 | InternalCFStat(cause, condition); |
1851 | | |
1852 | 360 | if (internal_cf_stat == InternalStats::INTERNAL_CF_STATS_ENUM_MAX) { |
1853 | 0 | continue; |
1854 | 0 | } |
1855 | | |
1856 | 360 | std::string name = |
1857 | 360 | WriteStallStatsMapKeys::CauseConditionCount(cause, condition); |
1858 | 360 | uint64_t stat = |
1859 | 360 | cf_stats_count_[static_cast<std::size_t>(internal_cf_stat)]; |
1860 | 360 | (*value)[name] = std::to_string(stat); |
1861 | | |
1862 | 360 | if (condition == WriteStallCondition::kDelayed) { |
1863 | 180 | total_delays += stat; |
1864 | 180 | } else if (condition == WriteStallCondition::kStopped) { |
1865 | 180 | total_stops += stat; |
1866 | 180 | } |
1867 | 360 | } |
1868 | 180 | } |
1869 | | |
1870 | 60 | (*value)[WriteStallStatsMapKeys:: |
1871 | 60 | CFL0FileCountLimitDelaysWithOngoingCompaction()] = |
1872 | 60 | std::to_string( |
1873 | 60 | cf_stats_count_[L0_FILE_COUNT_LIMIT_DELAYS_WITH_ONGOING_COMPACTION]); |
1874 | 60 | (*value)[WriteStallStatsMapKeys:: |
1875 | 60 | CFL0FileCountLimitStopsWithOngoingCompaction()] = |
1876 | 60 | std::to_string( |
1877 | 60 | cf_stats_count_[L0_FILE_COUNT_LIMIT_STOPS_WITH_ONGOING_COMPACTION]); |
1878 | | |
1879 | 60 | (*value)[WriteStallStatsMapKeys::TotalStops()] = std::to_string(total_stops); |
1880 | 60 | (*value)[WriteStallStatsMapKeys::TotalDelays()] = |
1881 | 60 | std::to_string(total_delays); |
1882 | 60 | } |
1883 | | |
1884 | | void InternalStats::DumpCFStatsWriteStall(std::string* value, |
1885 | 60 | uint64_t* total_stall_count) { |
1886 | 60 | assert(value); |
1887 | | |
1888 | 60 | std::map<std::string, std::string> write_stall_stats_map; |
1889 | 60 | DumpCFMapStatsWriteStall(&write_stall_stats_map); |
1890 | | |
1891 | 60 | std::ostringstream str; |
1892 | 60 | str << "Write Stall (count): "; |
1893 | | |
1894 | 60 | for (auto write_stall_stats_map_iter = write_stall_stats_map.begin(); |
1895 | 660 | write_stall_stats_map_iter != write_stall_stats_map.end(); |
1896 | 600 | write_stall_stats_map_iter++) { |
1897 | 600 | const auto& name_and_stat = *write_stall_stats_map_iter; |
1898 | 600 | str << name_and_stat.first << ": " << name_and_stat.second; |
1899 | 600 | if (std::next(write_stall_stats_map_iter) == write_stall_stats_map.end()) { |
1900 | 60 | str << "\n"; |
1901 | 540 | } else { |
1902 | 540 | str << ", "; |
1903 | 540 | } |
1904 | 600 | } |
1905 | | |
1906 | 60 | if (total_stall_count) { |
1907 | 60 | *total_stall_count = |
1908 | 60 | ParseUint64( |
1909 | 60 | write_stall_stats_map[WriteStallStatsMapKeys::TotalStops()]) + |
1910 | 60 | ParseUint64( |
1911 | 60 | write_stall_stats_map[WriteStallStatsMapKeys::TotalDelays()]); |
1912 | 60 | if (*total_stall_count > 0) { |
1913 | 0 | str << "interval: " << *total_stall_count - cf_stats_snapshot_.stall_count |
1914 | 0 | << " total count\n"; |
1915 | 0 | } |
1916 | 60 | } |
1917 | 60 | *value = str.str(); |
1918 | 60 | } |
1919 | | |
1920 | 0 | void InternalStats::DumpCFStats(std::string* value) { |
1921 | 0 | DumpCFStatsNoFileHistogram(/*is_periodic=*/false, value); |
1922 | 0 | DumpCFFileHistogram(value); |
1923 | 0 | } |
1924 | | |
1925 | | void InternalStats::DumpCFStatsNoFileHistogram(bool is_periodic, |
1926 | 60 | std::string* value) { |
1927 | 60 | char buf[2000]; |
1928 | | // Per-ColumnFamily stats |
1929 | 60 | PrintLevelStatsHeader(buf, sizeof(buf), cfd_->GetName(), "Level"); |
1930 | 60 | value->append(buf); |
1931 | | |
1932 | | // Print stats for each level |
1933 | 60 | const VersionStorageInfo* vstorage = cfd_->current()->storage_info(); |
1934 | 60 | std::map<int, std::map<LevelStatType, double>> levels_stats; |
1935 | 60 | CompactionStats compaction_stats_sum; |
1936 | 60 | DumpCFMapStats(vstorage, &levels_stats, &compaction_stats_sum); |
1937 | 480 | for (int l = 0; l < number_levels_; ++l) { |
1938 | 420 | if (levels_stats.find(l) != levels_stats.end()) { |
1939 | 8 | PrintLevelStats(buf, sizeof(buf), "L" + std::to_string(l), |
1940 | 8 | levels_stats[l]); |
1941 | 8 | value->append(buf); |
1942 | 8 | } |
1943 | 420 | } |
1944 | | |
1945 | | // Print sum of level stats |
1946 | 60 | PrintLevelStats(buf, sizeof(buf), "Sum", levels_stats[-1]); |
1947 | 60 | value->append(buf); |
1948 | | |
1949 | 60 | uint64_t flush_ingest = cf_stats_value_[BYTES_FLUSHED]; |
1950 | 60 | uint64_t add_file_ingest = cf_stats_value_[BYTES_INGESTED_ADD_FILE]; |
1951 | 60 | uint64_t ingest_files_addfile = cf_stats_value_[INGESTED_NUM_FILES_TOTAL]; |
1952 | 60 | uint64_t ingest_l0_files_addfile = |
1953 | 60 | cf_stats_value_[INGESTED_LEVEL0_NUM_FILES_TOTAL]; |
1954 | 60 | uint64_t ingest_keys_addfile = cf_stats_value_[INGESTED_NUM_KEYS_TOTAL]; |
1955 | | // Interval summary |
1956 | 60 | uint64_t interval_flush_ingest = |
1957 | 60 | flush_ingest - cf_stats_snapshot_.ingest_bytes_flush; |
1958 | 60 | uint64_t interval_add_file_inget = |
1959 | 60 | add_file_ingest - cf_stats_snapshot_.ingest_bytes_addfile; |
1960 | 60 | uint64_t interval_ingest = |
1961 | 60 | interval_flush_ingest + interval_add_file_inget + 1; |
1962 | 60 | CompactionStats interval_stats(compaction_stats_sum); |
1963 | 60 | interval_stats.Subtract(cf_stats_snapshot_.comp_stats); |
1964 | 60 | double w_amp = |
1965 | 60 | (interval_stats.bytes_written + interval_stats.bytes_written_blob) / |
1966 | 60 | static_cast<double>(interval_ingest); |
1967 | 60 | PrintLevelStats(buf, sizeof(buf), "Int", 0, 0, 0, 0, w_amp, interval_stats); |
1968 | 60 | value->append(buf); |
1969 | | |
1970 | 60 | PrintLevelStatsHeader(buf, sizeof(buf), cfd_->GetName(), "Priority"); |
1971 | 60 | value->append(buf); |
1972 | 60 | std::map<int, std::map<LevelStatType, double>> priorities_stats; |
1973 | 60 | DumpCFMapStatsByPriority(&priorities_stats); |
1974 | 300 | for (size_t priority = 0; priority < comp_stats_by_pri_.size(); ++priority) { |
1975 | 240 | if (priorities_stats.find(static_cast<int>(priority)) != |
1976 | 240 | priorities_stats.end()) { |
1977 | 2 | PrintLevelStats( |
1978 | 2 | buf, sizeof(buf), |
1979 | 2 | Env::PriorityToString(static_cast<Env::Priority>(priority)), |
1980 | 2 | priorities_stats[static_cast<int>(priority)]); |
1981 | 2 | value->append(buf); |
1982 | 2 | } |
1983 | 240 | } |
1984 | | |
1985 | 60 | const auto blob_st = vstorage->GetBlobStats(); |
1986 | | |
1987 | 60 | snprintf(buf, sizeof(buf), |
1988 | 60 | "\nBlob file count: %" ROCKSDB_PRIszt |
1989 | 60 | ", total size: %.1f GB, garbage size: %.1f GB, space amp: %.1f\n\n", |
1990 | 60 | vstorage->GetBlobFiles().size(), blob_st.total_file_size / kGB, |
1991 | 60 | blob_st.total_garbage_size / kGB, blob_st.space_amp); |
1992 | 60 | value->append(buf); |
1993 | | |
1994 | 60 | uint64_t now_micros = clock_->NowMicros(); |
1995 | 60 | double seconds_up = (now_micros - started_at_) / kMicrosInSec; |
1996 | 60 | double interval_seconds_up = seconds_up - cf_stats_snapshot_.seconds_up; |
1997 | 60 | snprintf(buf, sizeof(buf), "Uptime(secs): %.1f total, %.1f interval\n", |
1998 | 60 | seconds_up, interval_seconds_up); |
1999 | 60 | value->append(buf); |
2000 | 60 | snprintf(buf, sizeof(buf), "Flush(GB): cumulative %.3f, interval %.3f\n", |
2001 | 60 | flush_ingest / kGB, interval_flush_ingest / kGB); |
2002 | 60 | value->append(buf); |
2003 | 60 | snprintf(buf, sizeof(buf), "AddFile(GB): cumulative %.3f, interval %.3f\n", |
2004 | 60 | add_file_ingest / kGB, interval_add_file_inget / kGB); |
2005 | 60 | value->append(buf); |
2006 | | |
2007 | 60 | uint64_t interval_ingest_files_addfile = |
2008 | 60 | ingest_files_addfile - cf_stats_snapshot_.ingest_files_addfile; |
2009 | 60 | snprintf(buf, sizeof(buf), |
2010 | 60 | "AddFile(Total Files): cumulative %" PRIu64 ", interval %" PRIu64 |
2011 | 60 | "\n", |
2012 | 60 | ingest_files_addfile, interval_ingest_files_addfile); |
2013 | 60 | value->append(buf); |
2014 | | |
2015 | 60 | uint64_t interval_ingest_l0_files_addfile = |
2016 | 60 | ingest_l0_files_addfile - cf_stats_snapshot_.ingest_l0_files_addfile; |
2017 | 60 | snprintf(buf, sizeof(buf), |
2018 | 60 | "AddFile(L0 Files): cumulative %" PRIu64 ", interval %" PRIu64 "\n", |
2019 | 60 | ingest_l0_files_addfile, interval_ingest_l0_files_addfile); |
2020 | 60 | value->append(buf); |
2021 | | |
2022 | 60 | uint64_t interval_ingest_keys_addfile = |
2023 | 60 | ingest_keys_addfile - cf_stats_snapshot_.ingest_keys_addfile; |
2024 | 60 | snprintf(buf, sizeof(buf), |
2025 | 60 | "AddFile(Keys): cumulative %" PRIu64 ", interval %" PRIu64 "\n", |
2026 | 60 | ingest_keys_addfile, interval_ingest_keys_addfile); |
2027 | 60 | value->append(buf); |
2028 | | |
2029 | | // Compact |
2030 | 60 | uint64_t compact_bytes_read = 0; |
2031 | 60 | uint64_t compact_bytes_write = 0; |
2032 | 60 | uint64_t compact_micros = 0; |
2033 | 480 | for (int level = 0; level < number_levels_; level++) { |
2034 | 420 | compact_bytes_read += comp_stats_[level].bytes_read_output_level + |
2035 | 420 | comp_stats_[level].bytes_read_non_output_levels + |
2036 | 420 | comp_stats_[level].bytes_read_blob; |
2037 | 420 | compact_bytes_write += comp_stats_[level].bytes_written + |
2038 | 420 | comp_stats_[level].bytes_written_blob; |
2039 | 420 | compact_micros += comp_stats_[level].micros; |
2040 | 420 | } |
2041 | | |
2042 | 60 | snprintf(buf, sizeof(buf), |
2043 | 60 | "Cumulative compaction: %.2f GB write, %.2f MB/s write, " |
2044 | 60 | "%.2f GB read, %.2f MB/s read, %.1f seconds\n", |
2045 | 60 | compact_bytes_write / kGB, |
2046 | 60 | compact_bytes_write / kMB / std::max(seconds_up, 0.001), |
2047 | 60 | compact_bytes_read / kGB, |
2048 | 60 | compact_bytes_read / kMB / std::max(seconds_up, 0.001), |
2049 | 60 | compact_micros / kMicrosInSec); |
2050 | 60 | value->append(buf); |
2051 | | |
2052 | | // Compaction interval |
2053 | 60 | uint64_t interval_compact_bytes_write = |
2054 | 60 | compact_bytes_write - cf_stats_snapshot_.compact_bytes_write; |
2055 | 60 | uint64_t interval_compact_bytes_read = |
2056 | 60 | compact_bytes_read - cf_stats_snapshot_.compact_bytes_read; |
2057 | 60 | uint64_t interval_compact_micros = |
2058 | 60 | compact_micros - cf_stats_snapshot_.compact_micros; |
2059 | | |
2060 | 60 | snprintf( |
2061 | 60 | buf, sizeof(buf), |
2062 | 60 | "Interval compaction: %.2f GB write, %.2f MB/s write, " |
2063 | 60 | "%.2f GB read, %.2f MB/s read, %.1f seconds\n", |
2064 | 60 | interval_compact_bytes_write / kGB, |
2065 | 60 | interval_compact_bytes_write / kMB / std::max(interval_seconds_up, 0.001), |
2066 | 60 | interval_compact_bytes_read / kGB, |
2067 | 60 | interval_compact_bytes_read / kMB / std::max(interval_seconds_up, 0.001), |
2068 | 60 | interval_compact_micros / kMicrosInSec); |
2069 | 60 | value->append(buf); |
2070 | | |
2071 | 60 | snprintf(buf, sizeof(buf), |
2072 | 60 | "Estimated pending compaction bytes: %" PRIu64 "\n", |
2073 | 60 | vstorage->estimated_compaction_needed_bytes()); |
2074 | 60 | value->append(buf); |
2075 | | |
2076 | 60 | if (is_periodic) { |
2077 | 60 | cf_stats_snapshot_.compact_bytes_write = compact_bytes_write; |
2078 | 60 | cf_stats_snapshot_.compact_bytes_read = compact_bytes_read; |
2079 | 60 | cf_stats_snapshot_.compact_micros = compact_micros; |
2080 | 60 | } |
2081 | | |
2082 | 60 | std::string write_stall_stats; |
2083 | 60 | uint64_t total_stall_count; |
2084 | 60 | DumpCFStatsWriteStall(&write_stall_stats, &total_stall_count); |
2085 | 60 | value->append(write_stall_stats); |
2086 | | |
2087 | 60 | if (is_periodic) { |
2088 | 60 | cf_stats_snapshot_.seconds_up = seconds_up; |
2089 | 60 | cf_stats_snapshot_.ingest_bytes_flush = flush_ingest; |
2090 | 60 | cf_stats_snapshot_.ingest_bytes_addfile = add_file_ingest; |
2091 | 60 | cf_stats_snapshot_.ingest_files_addfile = ingest_files_addfile; |
2092 | 60 | cf_stats_snapshot_.ingest_l0_files_addfile = ingest_l0_files_addfile; |
2093 | 60 | cf_stats_snapshot_.ingest_keys_addfile = ingest_keys_addfile; |
2094 | 60 | cf_stats_snapshot_.comp_stats = compaction_stats_sum; |
2095 | 60 | cf_stats_snapshot_.stall_count = total_stall_count; |
2096 | 60 | } |
2097 | | |
2098 | | // Do not gather cache entry stats during CFStats because DB |
2099 | | // mutex is held. Only dump last cached collection (rely on DB |
2100 | | // periodic stats dump to update) |
2101 | 60 | if (cache_entry_stats_collector_) { |
2102 | 60 | CacheEntryRoleStats stats; |
2103 | | // thread safe |
2104 | 60 | cache_entry_stats_collector_->GetStats(&stats); |
2105 | | |
2106 | 60 | constexpr uint64_t kDayInMicros = uint64_t{86400} * 1000000U; |
2107 | | |
2108 | | // Skip if stats are extremely old (> 1 day, incl not yet populated) |
2109 | 60 | if (now_micros - stats.last_end_time_micros_ < kDayInMicros) { |
2110 | 60 | value->append(stats.ToString(clock_)); |
2111 | 60 | } |
2112 | 60 | } |
2113 | 60 | } |
2114 | | |
2115 | 60 | void InternalStats::DumpCFFileHistogram(std::string* value) { |
2116 | 60 | assert(value); |
2117 | 60 | assert(cfd_); |
2118 | | |
2119 | 60 | std::ostringstream oss; |
2120 | 60 | oss << "\n** File Read Latency Histogram By Level [" << cfd_->GetName() |
2121 | 60 | << "] **\n"; |
2122 | | |
2123 | 480 | for (int level = 0; level < number_levels_; level++) { |
2124 | 420 | if (!file_read_latency_[level].Empty()) { |
2125 | 0 | oss << "** Level " << level << " read latency histogram (micros):\n" |
2126 | 0 | << file_read_latency_[level].ToString() << '\n'; |
2127 | 0 | } |
2128 | 420 | } |
2129 | | |
2130 | 60 | if (!blob_file_read_latency_.Empty()) { |
2131 | 0 | oss << "** Blob file read latency histogram (micros):\n" |
2132 | 0 | << blob_file_read_latency_.ToString() << '\n'; |
2133 | 0 | } |
2134 | | |
2135 | 60 | value->append(oss.str()); |
2136 | 60 | } |
2137 | | |
2138 | | namespace { |
2139 | | |
2140 | | class SumPropertyAggregator : public IntPropertyAggregator { |
2141 | | public: |
2142 | 0 | SumPropertyAggregator() : aggregated_value_(0) {} |
2143 | | virtual ~SumPropertyAggregator() override = default; |
2144 | | |
2145 | 0 | void Add(ColumnFamilyData* cfd, uint64_t value) override { |
2146 | 0 | (void)cfd; |
2147 | 0 | aggregated_value_ += value; |
2148 | 0 | } |
2149 | | |
2150 | 0 | uint64_t Aggregate() const override { return aggregated_value_; } |
2151 | | |
2152 | | private: |
2153 | | uint64_t aggregated_value_; |
2154 | | }; |
2155 | | |
2156 | | // A block cache may be shared by multiple column families. |
2157 | | // BlockCachePropertyAggregator ensures that the same cache is only added once. |
2158 | | class BlockCachePropertyAggregator : public IntPropertyAggregator { |
2159 | | public: |
2160 | 0 | BlockCachePropertyAggregator() = default; |
2161 | 0 | virtual ~BlockCachePropertyAggregator() override = default; |
2162 | | |
2163 | 0 | void Add(ColumnFamilyData* cfd, uint64_t value) override { |
2164 | 0 | auto* table_factory = cfd->ioptions()->table_factory.get(); |
2165 | 0 | assert(table_factory != nullptr); |
2166 | 0 | Cache* cache = |
2167 | 0 | table_factory->GetOptions<Cache>(TableFactory::kBlockCacheOpts()); |
2168 | 0 | if (cache != nullptr) { |
2169 | 0 | block_cache_properties_.emplace(cache, value); |
2170 | 0 | } |
2171 | 0 | } |
2172 | | |
2173 | 0 | uint64_t Aggregate() const override { |
2174 | 0 | uint64_t sum = 0; |
2175 | 0 | for (const auto& p : block_cache_properties_) { |
2176 | 0 | sum += p.second; |
2177 | 0 | } |
2178 | 0 | return sum; |
2179 | 0 | } |
2180 | | |
2181 | | private: |
2182 | | std::unordered_map<Cache*, uint64_t> block_cache_properties_; |
2183 | | }; |
2184 | | |
2185 | | } // anonymous namespace |
2186 | | |
2187 | | std::unique_ptr<IntPropertyAggregator> CreateIntPropertyAggregator( |
2188 | 0 | const Slice& property) { |
2189 | 0 | if (property == DB::Properties::kBlockCacheCapacity || |
2190 | 0 | property == DB::Properties::kBlockCacheUsage || |
2191 | 0 | property == DB::Properties::kBlockCachePinnedUsage) { |
2192 | 0 | return std::make_unique<BlockCachePropertyAggregator>(); |
2193 | 0 | } else { |
2194 | 0 | return std::make_unique<SumPropertyAggregator>(); |
2195 | 0 | } |
2196 | 0 | } |
2197 | | |
2198 | | } // namespace ROCKSDB_NAMESPACE |