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).
5 // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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.
11 #include "db/internal_stats.h"
22 #include "cache/cache_entry_roles.h"
23 #include "cache/cache_entry_stats.h"
24 #include "db/column_family.h"
25 #include "db/db_impl/db_impl.h"
26 #include "port/port.h"
27 #include "rocksdb/system_clock.h"
28 #include "rocksdb/table.h"
29 #include "table/block_based/cachable_entry.h"
30 #include "util/hash_containers.h"
31 #include "util/string_util.h"
33 namespace ROCKSDB_NAMESPACE
{
37 const std::map
<LevelStatType
, LevelStat
> InternalStats::compaction_level_stats
=
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)"}},
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"}},
84 const double kMB
= 1048576.0;
85 const double kGB
= kMB
* 1024;
86 const double kMicrosInSec
= 1000000.0;
88 void PrintLevelStatsHeader(char* buf
, size_t len
, const std::string
& cf_name
,
89 const std::string
& group_by
) {
91 snprintf(buf
, len
, "\n** Compaction Stats [%s] **\n", cf_name
.c_str());
92 written_size
= std::min(written_size
, static_cast<int>(len
));
93 auto hdr
= [](LevelStatType t
) {
94 return InternalStats::compaction_level_stats
.at(t
).header_name
.c_str();
96 int line_size
= snprintf(
97 buf
+ written_size
, len
- written_size
,
98 "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s "
100 // Note that we skip COMPACTED_FILES and merge it with Files column
101 group_by
.c_str(), hdr(LevelStatType::NUM_FILES
),
102 hdr(LevelStatType::SIZE_BYTES
), hdr(LevelStatType::SCORE
),
103 hdr(LevelStatType::READ_GB
), hdr(LevelStatType::RN_GB
),
104 hdr(LevelStatType::RNP1_GB
), hdr(LevelStatType::WRITE_GB
),
105 hdr(LevelStatType::W_NEW_GB
), hdr(LevelStatType::MOVED_GB
),
106 hdr(LevelStatType::WRITE_AMP
), hdr(LevelStatType::READ_MBPS
),
107 hdr(LevelStatType::WRITE_MBPS
), hdr(LevelStatType::COMP_SEC
),
108 hdr(LevelStatType::COMP_CPU_SEC
), hdr(LevelStatType::COMP_COUNT
),
109 hdr(LevelStatType::AVG_SEC
), hdr(LevelStatType::KEY_IN
),
110 hdr(LevelStatType::KEY_DROP
), hdr(LevelStatType::R_BLOB_GB
),
111 hdr(LevelStatType::W_BLOB_GB
));
113 written_size
+= line_size
;
114 written_size
= std::min(written_size
, static_cast<int>(len
));
115 snprintf(buf
+ written_size
, len
- written_size
, "%s\n",
116 std::string(line_size
, '-').c_str());
119 void PrepareLevelStats(std::map
<LevelStatType
, double>* level_stats
,
120 int num_files
, int being_compacted
,
121 double total_file_size
, double score
, double w_amp
,
122 const InternalStats::CompactionStats
& stats
) {
123 const uint64_t bytes_read
= stats
.bytes_read_non_output_levels
+
124 stats
.bytes_read_output_level
+
125 stats
.bytes_read_blob
;
126 const uint64_t bytes_written
= stats
.bytes_written
+ stats
.bytes_written_blob
;
127 const int64_t bytes_new
= stats
.bytes_written
- stats
.bytes_read_output_level
;
128 const double elapsed
= (stats
.micros
+ 1) / kMicrosInSec
;
130 (*level_stats
)[LevelStatType::NUM_FILES
] = num_files
;
131 (*level_stats
)[LevelStatType::COMPACTED_FILES
] = being_compacted
;
132 (*level_stats
)[LevelStatType::SIZE_BYTES
] = total_file_size
;
133 (*level_stats
)[LevelStatType::SCORE
] = score
;
134 (*level_stats
)[LevelStatType::READ_GB
] = bytes_read
/ kGB
;
135 (*level_stats
)[LevelStatType::RN_GB
] =
136 stats
.bytes_read_non_output_levels
/ kGB
;
137 (*level_stats
)[LevelStatType::RNP1_GB
] = stats
.bytes_read_output_level
/ kGB
;
138 (*level_stats
)[LevelStatType::WRITE_GB
] = stats
.bytes_written
/ kGB
;
139 (*level_stats
)[LevelStatType::W_NEW_GB
] = bytes_new
/ kGB
;
140 (*level_stats
)[LevelStatType::MOVED_GB
] = stats
.bytes_moved
/ kGB
;
141 (*level_stats
)[LevelStatType::WRITE_AMP
] = w_amp
;
142 (*level_stats
)[LevelStatType::READ_MBPS
] = bytes_read
/ kMB
/ elapsed
;
143 (*level_stats
)[LevelStatType::WRITE_MBPS
] = bytes_written
/ kMB
/ elapsed
;
144 (*level_stats
)[LevelStatType::COMP_SEC
] = stats
.micros
/ kMicrosInSec
;
145 (*level_stats
)[LevelStatType::COMP_CPU_SEC
] = stats
.cpu_micros
/ kMicrosInSec
;
146 (*level_stats
)[LevelStatType::COMP_COUNT
] = stats
.count
;
147 (*level_stats
)[LevelStatType::AVG_SEC
] =
148 stats
.count
== 0 ? 0 : stats
.micros
/ kMicrosInSec
/ stats
.count
;
149 (*level_stats
)[LevelStatType::KEY_IN
] =
150 static_cast<double>(stats
.num_input_records
);
151 (*level_stats
)[LevelStatType::KEY_DROP
] =
152 static_cast<double>(stats
.num_dropped_records
);
153 (*level_stats
)[LevelStatType::R_BLOB_GB
] = stats
.bytes_read_blob
/ kGB
;
154 (*level_stats
)[LevelStatType::W_BLOB_GB
] = stats
.bytes_written_blob
/ kGB
;
157 void PrintLevelStats(char* buf
, size_t len
, const std::string
& name
,
158 const std::map
<LevelStatType
, double>& stat_value
) {
162 "%6d/%-3d " /* Files */
165 "%8.1f " /* Read(GB) */
166 "%7.1f " /* Rn(GB) */
167 "%8.1f " /* Rnp1(GB) */
168 "%9.1f " /* Write(GB) */
169 "%8.1f " /* Wnew(GB) */
170 "%9.1f " /* Moved(GB) */
172 "%8.1f " /* Rd(MB/s) */
173 "%8.1f " /* Wr(MB/s) */
174 "%9.2f " /* Comp(sec) */
175 "%17.2f " /* CompMergeCPU(sec) */
176 "%9d " /* Comp(cnt) */
177 "%8.3f " /* Avg(sec) */
180 "%9.1f " /* Rblob(GB) */
181 "%9.1f\n", /* Wblob(GB) */
182 name
.c_str(), static_cast<int>(stat_value
.at(LevelStatType::NUM_FILES
)),
183 static_cast<int>(stat_value
.at(LevelStatType::COMPACTED_FILES
)),
185 static_cast<uint64_t>(stat_value
.at(LevelStatType::SIZE_BYTES
)))
187 stat_value
.at(LevelStatType::SCORE
),
188 stat_value
.at(LevelStatType::READ_GB
),
189 stat_value
.at(LevelStatType::RN_GB
),
190 stat_value
.at(LevelStatType::RNP1_GB
),
191 stat_value
.at(LevelStatType::WRITE_GB
),
192 stat_value
.at(LevelStatType::W_NEW_GB
),
193 stat_value
.at(LevelStatType::MOVED_GB
),
194 stat_value
.at(LevelStatType::WRITE_AMP
),
195 stat_value
.at(LevelStatType::READ_MBPS
),
196 stat_value
.at(LevelStatType::WRITE_MBPS
),
197 stat_value
.at(LevelStatType::COMP_SEC
),
198 stat_value
.at(LevelStatType::COMP_CPU_SEC
),
199 static_cast<int>(stat_value
.at(LevelStatType::COMP_COUNT
)),
200 stat_value
.at(LevelStatType::AVG_SEC
),
202 static_cast<std::int64_t>(stat_value
.at(LevelStatType::KEY_IN
)))
205 static_cast<std::int64_t>(stat_value
.at(LevelStatType::KEY_DROP
)))
207 stat_value
.at(LevelStatType::R_BLOB_GB
),
208 stat_value
.at(LevelStatType::W_BLOB_GB
));
211 void PrintLevelStats(char* buf
, size_t len
, const std::string
& name
,
212 int num_files
, int being_compacted
, double total_file_size
,
213 double score
, double w_amp
,
214 const InternalStats::CompactionStats
& stats
) {
215 std::map
<LevelStatType
, double> level_stats
;
216 PrepareLevelStats(&level_stats
, num_files
, being_compacted
, total_file_size
,
217 score
, w_amp
, stats
);
218 PrintLevelStats(buf
, len
, name
, level_stats
);
221 // Assumes that trailing numbers represent an optional argument. This requires
222 // property names to not end with numbers.
223 std::pair
<Slice
, Slice
> GetPropertyNameAndArg(const Slice
& property
) {
224 Slice name
= property
, arg
= property
;
226 while (sfx_len
< property
.size() &&
227 isdigit(property
[property
.size() - sfx_len
- 1])) {
230 name
.remove_suffix(sfx_len
);
231 arg
.remove_prefix(property
.size() - sfx_len
);
234 } // anonymous namespace
236 static const std::string rocksdb_prefix
= "rocksdb.";
238 static const std::string num_files_at_level_prefix
= "num-files-at-level";
239 static const std::string compression_ratio_at_level_prefix
=
240 "compression-ratio-at-level";
241 static const std::string allstats
= "stats";
242 static const std::string sstables
= "sstables";
243 static const std::string cfstats
= "cfstats";
244 static const std::string cfstats_no_file_histogram
=
245 "cfstats-no-file-histogram";
246 static const std::string cf_file_histogram
= "cf-file-histogram";
247 static const std::string dbstats
= "dbstats";
248 static const std::string levelstats
= "levelstats";
249 static const std::string block_cache_entry_stats
= "block-cache-entry-stats";
250 static const std::string fast_block_cache_entry_stats
=
251 "fast-block-cache-entry-stats";
252 static const std::string num_immutable_mem_table
= "num-immutable-mem-table";
253 static const std::string num_immutable_mem_table_flushed
=
254 "num-immutable-mem-table-flushed";
255 static const std::string mem_table_flush_pending
= "mem-table-flush-pending";
256 static const std::string compaction_pending
= "compaction-pending";
257 static const std::string background_errors
= "background-errors";
258 static const std::string cur_size_active_mem_table
=
259 "cur-size-active-mem-table";
260 static const std::string cur_size_all_mem_tables
= "cur-size-all-mem-tables";
261 static const std::string size_all_mem_tables
= "size-all-mem-tables";
262 static const std::string num_entries_active_mem_table
=
263 "num-entries-active-mem-table";
264 static const std::string num_entries_imm_mem_tables
=
265 "num-entries-imm-mem-tables";
266 static const std::string num_deletes_active_mem_table
=
267 "num-deletes-active-mem-table";
268 static const std::string num_deletes_imm_mem_tables
=
269 "num-deletes-imm-mem-tables";
270 static const std::string estimate_num_keys
= "estimate-num-keys";
271 static const std::string estimate_table_readers_mem
=
272 "estimate-table-readers-mem";
273 static const std::string is_file_deletions_enabled
=
274 "is-file-deletions-enabled";
275 static const std::string num_snapshots
= "num-snapshots";
276 static const std::string oldest_snapshot_time
= "oldest-snapshot-time";
277 static const std::string oldest_snapshot_sequence
= "oldest-snapshot-sequence";
278 static const std::string num_live_versions
= "num-live-versions";
279 static const std::string current_version_number
=
280 "current-super-version-number";
281 static const std::string estimate_live_data_size
= "estimate-live-data-size";
282 static const std::string min_log_number_to_keep_str
= "min-log-number-to-keep";
283 static const std::string min_obsolete_sst_number_to_keep_str
=
284 "min-obsolete-sst-number-to-keep";
285 static const std::string base_level_str
= "base-level";
286 static const std::string total_sst_files_size
= "total-sst-files-size";
287 static const std::string live_sst_files_size
= "live-sst-files-size";
288 static const std::string live_sst_files_size_at_temperature
=
289 "live-sst-files-size-at-temperature";
290 static const std::string estimate_pending_comp_bytes
=
291 "estimate-pending-compaction-bytes";
292 static const std::string aggregated_table_properties
=
293 "aggregated-table-properties";
294 static const std::string aggregated_table_properties_at_level
=
295 aggregated_table_properties
+ "-at-level";
296 static const std::string num_running_compactions
= "num-running-compactions";
297 static const std::string num_running_flushes
= "num-running-flushes";
298 static const std::string actual_delayed_write_rate
=
299 "actual-delayed-write-rate";
300 static const std::string is_write_stopped
= "is-write-stopped";
301 static const std::string estimate_oldest_key_time
= "estimate-oldest-key-time";
302 static const std::string block_cache_capacity
= "block-cache-capacity";
303 static const std::string block_cache_usage
= "block-cache-usage";
304 static const std::string block_cache_pinned_usage
= "block-cache-pinned-usage";
305 static const std::string options_statistics
= "options-statistics";
306 static const std::string num_blob_files
= "num-blob-files";
307 static const std::string blob_stats
= "blob-stats";
308 static const std::string total_blob_file_size
= "total-blob-file-size";
309 static const std::string live_blob_file_size
= "live-blob-file-size";
310 static const std::string live_blob_file_garbage_size
=
311 "live-blob-file-garbage-size";
312 static const std::string blob_cache_capacity
= "blob-cache-capacity";
313 static const std::string blob_cache_usage
= "blob-cache-usage";
314 static const std::string blob_cache_pinned_usage
= "blob-cache-pinned-usage";
316 const std::string
DB::Properties::kNumFilesAtLevelPrefix
=
317 rocksdb_prefix
+ num_files_at_level_prefix
;
318 const std::string
DB::Properties::kCompressionRatioAtLevelPrefix
=
319 rocksdb_prefix
+ compression_ratio_at_level_prefix
;
320 const std::string
DB::Properties::kStats
= rocksdb_prefix
+ allstats
;
321 const std::string
DB::Properties::kSSTables
= rocksdb_prefix
+ sstables
;
322 const std::string
DB::Properties::kCFStats
= rocksdb_prefix
+ cfstats
;
323 const std::string
DB::Properties::kCFStatsNoFileHistogram
=
324 rocksdb_prefix
+ cfstats_no_file_histogram
;
325 const std::string
DB::Properties::kCFFileHistogram
=
326 rocksdb_prefix
+ cf_file_histogram
;
327 const std::string
DB::Properties::kDBStats
= rocksdb_prefix
+ dbstats
;
328 const std::string
DB::Properties::kLevelStats
= rocksdb_prefix
+ levelstats
;
329 const std::string
DB::Properties::kBlockCacheEntryStats
=
330 rocksdb_prefix
+ block_cache_entry_stats
;
331 const std::string
DB::Properties::kFastBlockCacheEntryStats
=
332 rocksdb_prefix
+ fast_block_cache_entry_stats
;
333 const std::string
DB::Properties::kNumImmutableMemTable
=
334 rocksdb_prefix
+ num_immutable_mem_table
;
335 const std::string
DB::Properties::kNumImmutableMemTableFlushed
=
336 rocksdb_prefix
+ num_immutable_mem_table_flushed
;
337 const std::string
DB::Properties::kMemTableFlushPending
=
338 rocksdb_prefix
+ mem_table_flush_pending
;
339 const std::string
DB::Properties::kCompactionPending
=
340 rocksdb_prefix
+ compaction_pending
;
341 const std::string
DB::Properties::kNumRunningCompactions
=
342 rocksdb_prefix
+ num_running_compactions
;
343 const std::string
DB::Properties::kNumRunningFlushes
=
344 rocksdb_prefix
+ num_running_flushes
;
345 const std::string
DB::Properties::kBackgroundErrors
=
346 rocksdb_prefix
+ background_errors
;
347 const std::string
DB::Properties::kCurSizeActiveMemTable
=
348 rocksdb_prefix
+ cur_size_active_mem_table
;
349 const std::string
DB::Properties::kCurSizeAllMemTables
=
350 rocksdb_prefix
+ cur_size_all_mem_tables
;
351 const std::string
DB::Properties::kSizeAllMemTables
=
352 rocksdb_prefix
+ size_all_mem_tables
;
353 const std::string
DB::Properties::kNumEntriesActiveMemTable
=
354 rocksdb_prefix
+ num_entries_active_mem_table
;
355 const std::string
DB::Properties::kNumEntriesImmMemTables
=
356 rocksdb_prefix
+ num_entries_imm_mem_tables
;
357 const std::string
DB::Properties::kNumDeletesActiveMemTable
=
358 rocksdb_prefix
+ num_deletes_active_mem_table
;
359 const std::string
DB::Properties::kNumDeletesImmMemTables
=
360 rocksdb_prefix
+ num_deletes_imm_mem_tables
;
361 const std::string
DB::Properties::kEstimateNumKeys
=
362 rocksdb_prefix
+ estimate_num_keys
;
363 const std::string
DB::Properties::kEstimateTableReadersMem
=
364 rocksdb_prefix
+ estimate_table_readers_mem
;
365 const std::string
DB::Properties::kIsFileDeletionsEnabled
=
366 rocksdb_prefix
+ is_file_deletions_enabled
;
367 const std::string
DB::Properties::kNumSnapshots
=
368 rocksdb_prefix
+ num_snapshots
;
369 const std::string
DB::Properties::kOldestSnapshotTime
=
370 rocksdb_prefix
+ oldest_snapshot_time
;
371 const std::string
DB::Properties::kOldestSnapshotSequence
=
372 rocksdb_prefix
+ oldest_snapshot_sequence
;
373 const std::string
DB::Properties::kNumLiveVersions
=
374 rocksdb_prefix
+ num_live_versions
;
375 const std::string
DB::Properties::kCurrentSuperVersionNumber
=
376 rocksdb_prefix
+ current_version_number
;
377 const std::string
DB::Properties::kEstimateLiveDataSize
=
378 rocksdb_prefix
+ estimate_live_data_size
;
379 const std::string
DB::Properties::kMinLogNumberToKeep
=
380 rocksdb_prefix
+ min_log_number_to_keep_str
;
381 const std::string
DB::Properties::kMinObsoleteSstNumberToKeep
=
382 rocksdb_prefix
+ min_obsolete_sst_number_to_keep_str
;
383 const std::string
DB::Properties::kTotalSstFilesSize
=
384 rocksdb_prefix
+ total_sst_files_size
;
385 const std::string
DB::Properties::kLiveSstFilesSize
=
386 rocksdb_prefix
+ live_sst_files_size
;
387 const std::string
DB::Properties::kBaseLevel
= rocksdb_prefix
+ base_level_str
;
388 const std::string
DB::Properties::kEstimatePendingCompactionBytes
=
389 rocksdb_prefix
+ estimate_pending_comp_bytes
;
390 const std::string
DB::Properties::kAggregatedTableProperties
=
391 rocksdb_prefix
+ aggregated_table_properties
;
392 const std::string
DB::Properties::kAggregatedTablePropertiesAtLevel
=
393 rocksdb_prefix
+ aggregated_table_properties_at_level
;
394 const std::string
DB::Properties::kActualDelayedWriteRate
=
395 rocksdb_prefix
+ actual_delayed_write_rate
;
396 const std::string
DB::Properties::kIsWriteStopped
=
397 rocksdb_prefix
+ is_write_stopped
;
398 const std::string
DB::Properties::kEstimateOldestKeyTime
=
399 rocksdb_prefix
+ estimate_oldest_key_time
;
400 const std::string
DB::Properties::kBlockCacheCapacity
=
401 rocksdb_prefix
+ block_cache_capacity
;
402 const std::string
DB::Properties::kBlockCacheUsage
=
403 rocksdb_prefix
+ block_cache_usage
;
404 const std::string
DB::Properties::kBlockCachePinnedUsage
=
405 rocksdb_prefix
+ block_cache_pinned_usage
;
406 const std::string
DB::Properties::kOptionsStatistics
=
407 rocksdb_prefix
+ options_statistics
;
408 const std::string
DB::Properties::kLiveSstFilesSizeAtTemperature
=
409 rocksdb_prefix
+ live_sst_files_size_at_temperature
;
410 const std::string
DB::Properties::kNumBlobFiles
=
411 rocksdb_prefix
+ num_blob_files
;
412 const std::string
DB::Properties::kBlobStats
= rocksdb_prefix
+ blob_stats
;
413 const std::string
DB::Properties::kTotalBlobFileSize
=
414 rocksdb_prefix
+ total_blob_file_size
;
415 const std::string
DB::Properties::kLiveBlobFileSize
=
416 rocksdb_prefix
+ live_blob_file_size
;
417 const std::string
DB::Properties::kLiveBlobFileGarbageSize
=
418 rocksdb_prefix
+ live_blob_file_garbage_size
;
419 const std::string
DB::Properties::kBlobCacheCapacity
=
420 rocksdb_prefix
+ blob_cache_capacity
;
421 const std::string
DB::Properties::kBlobCacheUsage
=
422 rocksdb_prefix
+ blob_cache_usage
;
423 const std::string
DB::Properties::kBlobCachePinnedUsage
=
424 rocksdb_prefix
+ blob_cache_pinned_usage
;
426 const std::string
InternalStats::kPeriodicCFStats
=
427 DB::Properties::kCFStats
+ ".periodic";
428 const int InternalStats::kMaxNoChangePeriodSinceDump
= 8;
430 const UnorderedMap
<std::string
, DBPropertyInfo
>
431 InternalStats::ppt_name_to_info
= {
432 {DB::Properties::kNumFilesAtLevelPrefix
,
433 {false, &InternalStats::HandleNumFilesAtLevel
, nullptr, nullptr,
435 {DB::Properties::kCompressionRatioAtLevelPrefix
,
436 {false, &InternalStats::HandleCompressionRatioAtLevelPrefix
, nullptr,
438 {DB::Properties::kLevelStats
,
439 {false, &InternalStats::HandleLevelStats
, nullptr, nullptr, nullptr}},
440 {DB::Properties::kStats
,
441 {false, &InternalStats::HandleStats
, nullptr, nullptr, nullptr}},
442 {DB::Properties::kCFStats
,
443 {false, &InternalStats::HandleCFStats
, nullptr,
444 &InternalStats::HandleCFMapStats
, nullptr}},
445 {InternalStats::kPeriodicCFStats
,
446 {false, &InternalStats::HandleCFStatsPeriodic
, nullptr, nullptr,
448 {DB::Properties::kCFStatsNoFileHistogram
,
449 {false, &InternalStats::HandleCFStatsNoFileHistogram
, nullptr, nullptr,
451 {DB::Properties::kCFFileHistogram
,
452 {false, &InternalStats::HandleCFFileHistogram
, nullptr, nullptr,
454 {DB::Properties::kDBStats
,
455 {false, &InternalStats::HandleDBStats
, nullptr,
456 &InternalStats::HandleDBMapStats
, nullptr}},
457 {DB::Properties::kBlockCacheEntryStats
,
458 {true, &InternalStats::HandleBlockCacheEntryStats
, nullptr,
459 &InternalStats::HandleBlockCacheEntryStatsMap
, nullptr}},
460 {DB::Properties::kFastBlockCacheEntryStats
,
461 {true, &InternalStats::HandleFastBlockCacheEntryStats
, nullptr,
462 &InternalStats::HandleFastBlockCacheEntryStatsMap
, nullptr}},
463 {DB::Properties::kSSTables
,
464 {false, &InternalStats::HandleSsTables
, nullptr, nullptr, nullptr}},
465 {DB::Properties::kAggregatedTableProperties
,
466 {false, &InternalStats::HandleAggregatedTableProperties
, nullptr,
467 &InternalStats::HandleAggregatedTablePropertiesMap
, nullptr}},
468 {DB::Properties::kAggregatedTablePropertiesAtLevel
,
469 {false, &InternalStats::HandleAggregatedTablePropertiesAtLevel
,
470 nullptr, &InternalStats::HandleAggregatedTablePropertiesAtLevelMap
,
472 {DB::Properties::kNumImmutableMemTable
,
473 {false, nullptr, &InternalStats::HandleNumImmutableMemTable
, nullptr,
475 {DB::Properties::kNumImmutableMemTableFlushed
,
476 {false, nullptr, &InternalStats::HandleNumImmutableMemTableFlushed
,
478 {DB::Properties::kMemTableFlushPending
,
479 {false, nullptr, &InternalStats::HandleMemTableFlushPending
, nullptr,
481 {DB::Properties::kCompactionPending
,
482 {false, nullptr, &InternalStats::HandleCompactionPending
, nullptr,
484 {DB::Properties::kBackgroundErrors
,
485 {false, nullptr, &InternalStats::HandleBackgroundErrors
, nullptr,
487 {DB::Properties::kCurSizeActiveMemTable
,
488 {false, nullptr, &InternalStats::HandleCurSizeActiveMemTable
, nullptr,
490 {DB::Properties::kCurSizeAllMemTables
,
491 {false, nullptr, &InternalStats::HandleCurSizeAllMemTables
, nullptr,
493 {DB::Properties::kSizeAllMemTables
,
494 {false, nullptr, &InternalStats::HandleSizeAllMemTables
, nullptr,
496 {DB::Properties::kNumEntriesActiveMemTable
,
497 {false, nullptr, &InternalStats::HandleNumEntriesActiveMemTable
,
499 {DB::Properties::kNumEntriesImmMemTables
,
500 {false, nullptr, &InternalStats::HandleNumEntriesImmMemTables
, nullptr,
502 {DB::Properties::kNumDeletesActiveMemTable
,
503 {false, nullptr, &InternalStats::HandleNumDeletesActiveMemTable
,
505 {DB::Properties::kNumDeletesImmMemTables
,
506 {false, nullptr, &InternalStats::HandleNumDeletesImmMemTables
, nullptr,
508 {DB::Properties::kEstimateNumKeys
,
509 {false, nullptr, &InternalStats::HandleEstimateNumKeys
, nullptr,
511 {DB::Properties::kEstimateTableReadersMem
,
512 {true, nullptr, &InternalStats::HandleEstimateTableReadersMem
, nullptr,
514 {DB::Properties::kIsFileDeletionsEnabled
,
515 {false, nullptr, &InternalStats::HandleIsFileDeletionsEnabled
, nullptr,
517 {DB::Properties::kNumSnapshots
,
518 {false, nullptr, &InternalStats::HandleNumSnapshots
, nullptr,
520 {DB::Properties::kOldestSnapshotTime
,
521 {false, nullptr, &InternalStats::HandleOldestSnapshotTime
, nullptr,
523 {DB::Properties::kOldestSnapshotSequence
,
524 {false, nullptr, &InternalStats::HandleOldestSnapshotSequence
, nullptr,
526 {DB::Properties::kNumLiveVersions
,
527 {false, nullptr, &InternalStats::HandleNumLiveVersions
, nullptr,
529 {DB::Properties::kCurrentSuperVersionNumber
,
530 {false, nullptr, &InternalStats::HandleCurrentSuperVersionNumber
,
532 {DB::Properties::kEstimateLiveDataSize
,
533 {true, nullptr, &InternalStats::HandleEstimateLiveDataSize
, nullptr,
535 {DB::Properties::kMinLogNumberToKeep
,
536 {false, nullptr, &InternalStats::HandleMinLogNumberToKeep
, nullptr,
538 {DB::Properties::kMinObsoleteSstNumberToKeep
,
539 {false, nullptr, &InternalStats::HandleMinObsoleteSstNumberToKeep
,
541 {DB::Properties::kBaseLevel
,
542 {false, nullptr, &InternalStats::HandleBaseLevel
, nullptr, nullptr}},
543 {DB::Properties::kTotalSstFilesSize
,
544 {false, nullptr, &InternalStats::HandleTotalSstFilesSize
, nullptr,
546 {DB::Properties::kLiveSstFilesSize
,
547 {false, nullptr, &InternalStats::HandleLiveSstFilesSize
, nullptr,
549 {DB::Properties::kLiveSstFilesSizeAtTemperature
,
550 {false, &InternalStats::HandleLiveSstFilesSizeAtTemperature
, nullptr,
552 {DB::Properties::kEstimatePendingCompactionBytes
,
553 {false, nullptr, &InternalStats::HandleEstimatePendingCompactionBytes
,
555 {DB::Properties::kNumRunningFlushes
,
556 {false, nullptr, &InternalStats::HandleNumRunningFlushes
, nullptr,
558 {DB::Properties::kNumRunningCompactions
,
559 {false, nullptr, &InternalStats::HandleNumRunningCompactions
, nullptr,
561 {DB::Properties::kActualDelayedWriteRate
,
562 {false, nullptr, &InternalStats::HandleActualDelayedWriteRate
, nullptr,
564 {DB::Properties::kIsWriteStopped
,
565 {false, nullptr, &InternalStats::HandleIsWriteStopped
, nullptr,
567 {DB::Properties::kEstimateOldestKeyTime
,
568 {false, nullptr, &InternalStats::HandleEstimateOldestKeyTime
, nullptr,
570 {DB::Properties::kBlockCacheCapacity
,
571 {false, nullptr, &InternalStats::HandleBlockCacheCapacity
, nullptr,
573 {DB::Properties::kBlockCacheUsage
,
574 {false, nullptr, &InternalStats::HandleBlockCacheUsage
, nullptr,
576 {DB::Properties::kBlockCachePinnedUsage
,
577 {false, nullptr, &InternalStats::HandleBlockCachePinnedUsage
, nullptr,
579 {DB::Properties::kOptionsStatistics
,
580 {true, nullptr, nullptr, nullptr,
581 &DBImpl::GetPropertyHandleOptionsStatistics
}},
582 {DB::Properties::kNumBlobFiles
,
583 {false, nullptr, &InternalStats::HandleNumBlobFiles
, nullptr,
585 {DB::Properties::kBlobStats
,
586 {false, &InternalStats::HandleBlobStats
, nullptr, nullptr, nullptr}},
587 {DB::Properties::kTotalBlobFileSize
,
588 {false, nullptr, &InternalStats::HandleTotalBlobFileSize
, nullptr,
590 {DB::Properties::kLiveBlobFileSize
,
591 {false, nullptr, &InternalStats::HandleLiveBlobFileSize
, nullptr,
593 {DB::Properties::kLiveBlobFileGarbageSize
,
594 {false, nullptr, &InternalStats::HandleLiveBlobFileGarbageSize
,
596 {DB::Properties::kBlobCacheCapacity
,
597 {false, nullptr, &InternalStats::HandleBlobCacheCapacity
, nullptr,
599 {DB::Properties::kBlobCacheUsage
,
600 {false, nullptr, &InternalStats::HandleBlobCacheUsage
, nullptr,
602 {DB::Properties::kBlobCachePinnedUsage
,
603 {false, nullptr, &InternalStats::HandleBlobCachePinnedUsage
, nullptr,
607 InternalStats::InternalStats(int num_levels
, SystemClock
* clock
,
608 ColumnFamilyData
* cfd
)
612 comp_stats_(num_levels
),
613 comp_stats_by_pri_(Env::Priority::TOTAL
),
614 file_read_latency_(num_levels
),
615 has_cf_change_since_dump_(true),
617 number_levels_(num_levels
),
620 started_at_(clock
->NowMicros()) {
621 Cache
* block_cache
= GetBlockCacheForStats();
623 // Extract or create stats collector. Could fail in rare cases.
624 Status s
= CacheEntryStatsCollector
<CacheEntryRoleStats
>::GetShared(
625 block_cache
, clock_
, &cache_entry_stats_collector_
);
627 assert(cache_entry_stats_collector_
);
629 assert(!cache_entry_stats_collector_
);
634 void InternalStats::TEST_GetCacheEntryRoleStats(CacheEntryRoleStats
* stats
,
636 CollectCacheEntryStats(foreground
);
637 if (cache_entry_stats_collector_
) {
638 cache_entry_stats_collector_
->GetStats(stats
);
642 void InternalStats::CollectCacheEntryStats(bool foreground
) {
643 // This function is safe to call from any thread because
644 // cache_entry_stats_collector_ field is const after constructor
645 // and ->GetStats does its own synchronization, which also suffices for
646 // cache_entry_stats_.
648 if (!cache_entry_stats_collector_
) {
649 return; // nothing to do (e.g. no block cache)
652 // For "background" collections, strictly cap the collection time by
653 // expanding effective cache TTL. For foreground, be more aggressive about
654 // getting latest data.
655 int min_interval_seconds
= foreground
? 10 : 180;
656 // 1/500 = max of 0.2% of one CPU thread
657 int min_interval_factor
= foreground
? 10 : 500;
658 cache_entry_stats_collector_
->CollectStats(min_interval_seconds
,
659 min_interval_factor
);
662 std::function
<void(const Slice
&, void*, size_t, Cache::DeleterFn
)>
663 InternalStats::CacheEntryRoleStats::GetEntryCallback() {
664 return [&](const Slice
& /*key*/, void* /*value*/, size_t charge
,
665 Cache::DeleterFn deleter
) {
666 auto e
= role_map_
.find(deleter
);
668 if (e
== role_map_
.end()) {
669 role_idx
= static_cast<size_t>(CacheEntryRole::kMisc
);
671 role_idx
= static_cast<size_t>(e
->second
);
673 entry_counts
[role_idx
]++;
674 total_charges
[role_idx
] += charge
;
678 void InternalStats::CacheEntryRoleStats::BeginCollection(
679 Cache
* cache
, SystemClock
*, uint64_t start_time_micros
) {
681 last_start_time_micros_
= start_time_micros
;
683 role_map_
= CopyCacheDeleterRoleMap();
684 std::ostringstream str
;
685 str
<< cache
->Name() << "@" << static_cast<void*>(cache
) << "#"
686 << port::GetProcessID();
687 cache_id
= str
.str();
688 cache_capacity
= cache
->GetCapacity();
689 cache_usage
= cache
->GetUsage();
690 table_size
= cache
->GetTableAddressCount();
691 occupancy
= cache
->GetOccupancyCount();
694 void InternalStats::CacheEntryRoleStats::EndCollection(
695 Cache
*, SystemClock
*, uint64_t end_time_micros
) {
696 last_end_time_micros_
= end_time_micros
;
699 void InternalStats::CacheEntryRoleStats::SkippedCollection() {
700 ++copies_of_last_collection
;
703 uint64_t InternalStats::CacheEntryRoleStats::GetLastDurationMicros() const {
704 if (last_end_time_micros_
> last_start_time_micros_
) {
705 return last_end_time_micros_
- last_start_time_micros_
;
711 std::string
InternalStats::CacheEntryRoleStats::ToString(
712 SystemClock
* clock
) const {
713 std::ostringstream str
;
714 str
<< "Block cache " << cache_id
715 << " capacity: " << BytesToHumanString(cache_capacity
)
716 << " usage: " << BytesToHumanString(cache_usage
)
717 << " table_size: " << table_size
<< " occupancy: " << occupancy
718 << " collections: " << collection_count
719 << " last_copies: " << copies_of_last_collection
720 << " last_secs: " << (GetLastDurationMicros() / 1000000.0)
722 << ((clock
->NowMicros() - last_end_time_micros_
) / 1000000U) << "\n";
723 str
<< "Block cache entry stats(count,size,portion):";
724 for (size_t i
= 0; i
< kNumCacheEntryRoles
; ++i
) {
725 if (entry_counts
[i
] > 0) {
726 str
<< " " << kCacheEntryRoleToCamelString
[i
] << "(" << entry_counts
[i
]
727 << "," << BytesToHumanString(total_charges
[i
]) << ","
728 << (100.0 * total_charges
[i
] / cache_capacity
) << "%)";
735 void InternalStats::CacheEntryRoleStats::ToMap(
736 std::map
<std::string
, std::string
>* values
, SystemClock
* clock
) const {
739 v
[BlockCacheEntryStatsMapKeys::CacheId()] = cache_id
;
740 v
[BlockCacheEntryStatsMapKeys::CacheCapacityBytes()] =
741 std::to_string(cache_capacity
);
742 v
[BlockCacheEntryStatsMapKeys::LastCollectionDurationSeconds()] =
743 std::to_string(GetLastDurationMicros() / 1000000.0);
744 v
[BlockCacheEntryStatsMapKeys::LastCollectionAgeSeconds()] =
745 std::to_string((clock
->NowMicros() - last_end_time_micros_
) / 1000000U);
746 for (size_t i
= 0; i
< kNumCacheEntryRoles
; ++i
) {
747 auto role
= static_cast<CacheEntryRole
>(i
);
748 v
[BlockCacheEntryStatsMapKeys::EntryCount(role
)] =
749 std::to_string(entry_counts
[i
]);
750 v
[BlockCacheEntryStatsMapKeys::UsedBytes(role
)] =
751 std::to_string(total_charges
[i
]);
752 v
[BlockCacheEntryStatsMapKeys::UsedPercent(role
)] =
753 std::to_string(100.0 * total_charges
[i
] / cache_capacity
);
757 bool InternalStats::HandleBlockCacheEntryStatsInternal(std::string
* value
,
759 if (!cache_entry_stats_collector_
) {
762 CollectCacheEntryStats(!fast
/* foreground */);
763 CacheEntryRoleStats stats
;
764 cache_entry_stats_collector_
->GetStats(&stats
);
765 *value
= stats
.ToString(clock_
);
769 bool InternalStats::HandleBlockCacheEntryStatsMapInternal(
770 std::map
<std::string
, std::string
>* values
, bool fast
) {
771 if (!cache_entry_stats_collector_
) {
774 CollectCacheEntryStats(!fast
/* foreground */);
775 CacheEntryRoleStats stats
;
776 cache_entry_stats_collector_
->GetStats(&stats
);
777 stats
.ToMap(values
, clock_
);
781 bool InternalStats::HandleBlockCacheEntryStats(std::string
* value
,
783 return HandleBlockCacheEntryStatsInternal(value
, false /* fast */);
786 bool InternalStats::HandleBlockCacheEntryStatsMap(
787 std::map
<std::string
, std::string
>* values
, Slice
/*suffix*/) {
788 return HandleBlockCacheEntryStatsMapInternal(values
, false /* fast */);
791 bool InternalStats::HandleFastBlockCacheEntryStats(std::string
* value
,
793 return HandleBlockCacheEntryStatsInternal(value
, true /* fast */);
796 bool InternalStats::HandleFastBlockCacheEntryStatsMap(
797 std::map
<std::string
, std::string
>* values
, Slice
/*suffix*/) {
798 return HandleBlockCacheEntryStatsMapInternal(values
, true /* fast */);
801 bool InternalStats::HandleLiveSstFilesSizeAtTemperature(std::string
* value
,
803 uint64_t temperature
;
804 bool ok
= ConsumeDecimalNumber(&suffix
, &temperature
) && suffix
.empty();
810 const auto* vstorage
= cfd_
->current()->storage_info();
811 for (int level
= 0; level
< vstorage
->num_levels(); level
++) {
812 for (const auto& file_meta
: vstorage
->LevelFiles(level
)) {
813 if (static_cast<uint8_t>(file_meta
->temperature
) == temperature
) {
814 size
+= file_meta
->fd
.GetFileSize();
819 *value
= std::to_string(size
);
823 bool InternalStats::HandleNumBlobFiles(uint64_t* value
, DBImpl
* /*db*/,
824 Version
* /*version*/) {
828 const auto* current
= cfd_
->current();
831 const auto* vstorage
= current
->storage_info();
834 const auto& blob_files
= vstorage
->GetBlobFiles();
836 *value
= blob_files
.size();
841 bool InternalStats::HandleBlobStats(std::string
* value
, Slice
/*suffix*/) {
845 const auto* current
= cfd_
->current();
848 const auto* vstorage
= current
->storage_info();
851 const auto blob_st
= vstorage
->GetBlobStats();
853 std::ostringstream oss
;
855 oss
<< "Number of blob files: " << vstorage
->GetBlobFiles().size()
856 << "\nTotal size of blob files: " << blob_st
.total_file_size
857 << "\nTotal size of garbage in blob files: " << blob_st
.total_garbage_size
858 << "\nBlob file space amplification: " << blob_st
.space_amp
<< '\n';
860 value
->append(oss
.str());
865 bool InternalStats::HandleTotalBlobFileSize(uint64_t* value
, DBImpl
* /*db*/,
866 Version
* /*version*/) {
870 *value
= cfd_
->GetTotalBlobFileSize();
875 bool InternalStats::HandleLiveBlobFileSize(uint64_t* value
, DBImpl
* /*db*/,
876 Version
* /*version*/) {
880 const auto* current
= cfd_
->current();
883 const auto* vstorage
= current
->storage_info();
886 *value
= vstorage
->GetBlobStats().total_file_size
;
891 bool InternalStats::HandleLiveBlobFileGarbageSize(uint64_t* value
,
893 Version
* /*version*/) {
897 const auto* current
= cfd_
->current();
900 const auto* vstorage
= current
->storage_info();
903 *value
= vstorage
->GetBlobStats().total_garbage_size
;
908 Cache
* InternalStats::GetBlobCacheForStats() {
909 return cfd_
->ioptions()->blob_cache
.get();
912 bool InternalStats::HandleBlobCacheCapacity(uint64_t* value
, DBImpl
* /*db*/,
913 Version
* /*version*/) {
914 Cache
* blob_cache
= GetBlobCacheForStats();
916 *value
= static_cast<uint64_t>(blob_cache
->GetCapacity());
922 bool InternalStats::HandleBlobCacheUsage(uint64_t* value
, DBImpl
* /*db*/,
923 Version
* /*version*/) {
924 Cache
* blob_cache
= GetBlobCacheForStats();
926 *value
= static_cast<uint64_t>(blob_cache
->GetUsage());
932 bool InternalStats::HandleBlobCachePinnedUsage(uint64_t* value
, DBImpl
* /*db*/,
933 Version
* /*version*/) {
934 Cache
* blob_cache
= GetBlobCacheForStats();
936 *value
= static_cast<uint64_t>(blob_cache
->GetPinnedUsage());
942 const DBPropertyInfo
* GetPropertyInfo(const Slice
& property
) {
943 std::string ppt_name
= GetPropertyNameAndArg(property
).first
.ToString();
944 auto ppt_info_iter
= InternalStats::ppt_name_to_info
.find(ppt_name
);
945 if (ppt_info_iter
== InternalStats::ppt_name_to_info
.end()) {
948 return &ppt_info_iter
->second
;
951 bool InternalStats::GetStringProperty(const DBPropertyInfo
& property_info
,
952 const Slice
& property
,
953 std::string
* value
) {
954 assert(value
!= nullptr);
955 assert(property_info
.handle_string
!= nullptr);
956 Slice arg
= GetPropertyNameAndArg(property
).second
;
957 return (this->*(property_info
.handle_string
))(value
, arg
);
960 bool InternalStats::GetMapProperty(const DBPropertyInfo
& property_info
,
961 const Slice
& property
,
962 std::map
<std::string
, std::string
>* value
) {
963 assert(value
!= nullptr);
964 assert(property_info
.handle_map
!= nullptr);
965 Slice arg
= GetPropertyNameAndArg(property
).second
;
966 return (this->*(property_info
.handle_map
))(value
, arg
);
969 bool InternalStats::GetIntProperty(const DBPropertyInfo
& property_info
,
970 uint64_t* value
, DBImpl
* db
) {
971 assert(value
!= nullptr);
972 assert(property_info
.handle_int
!= nullptr &&
973 !property_info
.need_out_of_mutex
);
974 db
->mutex_
.AssertHeld();
975 return (this->*(property_info
.handle_int
))(value
, db
, nullptr /* version */);
978 bool InternalStats::GetIntPropertyOutOfMutex(
979 const DBPropertyInfo
& property_info
, Version
* version
, uint64_t* value
) {
980 assert(value
!= nullptr);
981 assert(property_info
.handle_int
!= nullptr &&
982 property_info
.need_out_of_mutex
);
983 return (this->*(property_info
.handle_int
))(value
, nullptr /* db */, version
);
986 bool InternalStats::HandleNumFilesAtLevel(std::string
* value
, Slice suffix
) {
988 const auto* vstorage
= cfd_
->current()->storage_info();
989 bool ok
= ConsumeDecimalNumber(&suffix
, &level
) && suffix
.empty();
990 if (!ok
|| static_cast<int>(level
) >= number_levels_
) {
994 snprintf(buf
, sizeof(buf
), "%d",
995 vstorage
->NumLevelFiles(static_cast<int>(level
)));
1001 bool InternalStats::HandleCompressionRatioAtLevelPrefix(std::string
* value
,
1004 const auto* vstorage
= cfd_
->current()->storage_info();
1005 bool ok
= ConsumeDecimalNumber(&suffix
, &level
) && suffix
.empty();
1006 if (!ok
|| level
>= static_cast<uint64_t>(number_levels_
)) {
1009 *value
= std::to_string(
1010 vstorage
->GetEstimatedCompressionRatioAtLevel(static_cast<int>(level
)));
1014 bool InternalStats::HandleLevelStats(std::string
* value
, Slice
/*suffix*/) {
1016 const auto* vstorage
= cfd_
->current()->storage_info();
1017 snprintf(buf
, sizeof(buf
),
1018 "Level Files Size(MB)\n"
1019 "--------------------\n");
1022 for (int level
= 0; level
< number_levels_
; level
++) {
1023 snprintf(buf
, sizeof(buf
), "%3d %8d %8.0f\n", level
,
1024 vstorage
->NumLevelFiles(level
),
1025 vstorage
->NumLevelBytes(level
) / kMB
);
1031 bool InternalStats::HandleStats(std::string
* value
, Slice suffix
) {
1032 if (!HandleCFStats(value
, suffix
)) {
1035 if (!HandleDBStats(value
, suffix
)) {
1041 bool InternalStats::HandleCFMapStats(
1042 std::map
<std::string
, std::string
>* cf_stats
, Slice
/*suffix*/) {
1043 DumpCFMapStats(cf_stats
);
1047 bool InternalStats::HandleCFStats(std::string
* value
, Slice
/*suffix*/) {
1052 bool InternalStats::HandleCFStatsPeriodic(std::string
* value
,
1054 bool has_change
= has_cf_change_since_dump_
;
1056 // If file histogram changes, there is activity in this period too.
1057 uint64_t new_histogram_num
= 0;
1058 for (int level
= 0; level
< number_levels_
; level
++) {
1059 new_histogram_num
+= file_read_latency_
[level
].num();
1061 new_histogram_num
+= blob_file_read_latency_
.num();
1062 if (new_histogram_num
!= last_histogram_num
) {
1064 last_histogram_num
= new_histogram_num
;
1068 no_cf_change_period_since_dump_
= 0;
1069 has_cf_change_since_dump_
= false;
1070 } else if (no_cf_change_period_since_dump_
++ > 0) {
1071 // Not ready to sync
1072 if (no_cf_change_period_since_dump_
== kMaxNoChangePeriodSinceDump
) {
1073 // Next periodic, we need to dump stats even if there is no change.
1074 no_cf_change_period_since_dump_
= 0;
1079 DumpCFStatsNoFileHistogram(/*is_periodic=*/true, value
);
1080 DumpCFFileHistogram(value
);
1084 bool InternalStats::HandleCFStatsNoFileHistogram(std::string
* value
,
1086 DumpCFStatsNoFileHistogram(/*is_periodic=*/false, value
);
1090 bool InternalStats::HandleCFFileHistogram(std::string
* value
,
1092 DumpCFFileHistogram(value
);
1096 bool InternalStats::HandleDBMapStats(
1097 std::map
<std::string
, std::string
>* db_stats
, Slice
/*suffix*/) {
1098 DumpDBMapStats(db_stats
);
1102 bool InternalStats::HandleDBStats(std::string
* value
, Slice
/*suffix*/) {
1107 bool InternalStats::HandleSsTables(std::string
* value
, Slice
/*suffix*/) {
1108 auto* current
= cfd_
->current();
1109 *value
= current
->DebugString(true, true);
1113 bool InternalStats::HandleAggregatedTableProperties(std::string
* value
,
1115 std::shared_ptr
<const TableProperties
> tp
;
1116 auto s
= cfd_
->current()->GetAggregatedTableProperties(&tp
);
1120 *value
= tp
->ToString();
1124 static std::map
<std::string
, std::string
> MapUint64ValuesToString(
1125 const std::map
<std::string
, uint64_t>& from
) {
1126 std::map
<std::string
, std::string
> to
;
1127 for (const auto& e
: from
) {
1128 to
[e
.first
] = std::to_string(e
.second
);
1133 bool InternalStats::HandleAggregatedTablePropertiesMap(
1134 std::map
<std::string
, std::string
>* values
, Slice
/*suffix*/) {
1135 std::shared_ptr
<const TableProperties
> tp
;
1136 auto s
= cfd_
->current()->GetAggregatedTableProperties(&tp
);
1140 *values
= MapUint64ValuesToString(tp
->GetAggregatablePropertiesAsMap());
1144 bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string
* values
,
1147 bool ok
= ConsumeDecimalNumber(&suffix
, &level
) && suffix
.empty();
1148 if (!ok
|| static_cast<int>(level
) >= number_levels_
) {
1151 std::shared_ptr
<const TableProperties
> tp
;
1152 auto s
= cfd_
->current()->GetAggregatedTableProperties(
1153 &tp
, static_cast<int>(level
));
1157 *values
= tp
->ToString();
1161 bool InternalStats::HandleAggregatedTablePropertiesAtLevelMap(
1162 std::map
<std::string
, std::string
>* values
, Slice suffix
) {
1164 bool ok
= ConsumeDecimalNumber(&suffix
, &level
) && suffix
.empty();
1165 if (!ok
|| static_cast<int>(level
) >= number_levels_
) {
1168 std::shared_ptr
<const TableProperties
> tp
;
1169 auto s
= cfd_
->current()->GetAggregatedTableProperties(
1170 &tp
, static_cast<int>(level
));
1174 *values
= MapUint64ValuesToString(tp
->GetAggregatablePropertiesAsMap());
1178 bool InternalStats::HandleNumImmutableMemTable(uint64_t* value
, DBImpl
* /*db*/,
1179 Version
* /*version*/) {
1180 *value
= cfd_
->imm()->NumNotFlushed();
1184 bool InternalStats::HandleNumImmutableMemTableFlushed(uint64_t* value
,
1186 Version
* /*version*/) {
1187 *value
= cfd_
->imm()->NumFlushed();
1191 bool InternalStats::HandleMemTableFlushPending(uint64_t* value
, DBImpl
* /*db*/,
1192 Version
* /*version*/) {
1193 *value
= (cfd_
->imm()->IsFlushPending() ? 1 : 0);
1197 bool InternalStats::HandleNumRunningFlushes(uint64_t* value
, DBImpl
* db
,
1198 Version
* /*version*/) {
1199 *value
= db
->num_running_flushes();
1203 bool InternalStats::HandleCompactionPending(uint64_t* value
, DBImpl
* /*db*/,
1204 Version
* /*version*/) {
1205 // 1 if the system already determines at least one compaction is needed.
1207 const auto* vstorage
= cfd_
->current()->storage_info();
1208 *value
= (cfd_
->compaction_picker()->NeedsCompaction(vstorage
) ? 1 : 0);
1212 bool InternalStats::HandleNumRunningCompactions(uint64_t* value
, DBImpl
* db
,
1213 Version
* /*version*/) {
1214 *value
= db
->num_running_compactions_
;
1218 bool InternalStats::HandleBackgroundErrors(uint64_t* value
, DBImpl
* /*db*/,
1219 Version
* /*version*/) {
1220 // Accumulated number of errors in background flushes or compactions.
1221 *value
= GetBackgroundErrorCount();
1225 bool InternalStats::HandleCurSizeActiveMemTable(uint64_t* value
, DBImpl
* /*db*/,
1226 Version
* /*version*/) {
1227 // Current size of the active memtable
1228 // Using ApproximateMemoryUsageFast to avoid the need for synchronization
1229 *value
= cfd_
->mem()->ApproximateMemoryUsageFast();
1233 bool InternalStats::HandleCurSizeAllMemTables(uint64_t* value
, DBImpl
* /*db*/,
1234 Version
* /*version*/) {
1235 // Current size of the active memtable + immutable memtables
1236 // Using ApproximateMemoryUsageFast to avoid the need for synchronization
1237 *value
= cfd_
->mem()->ApproximateMemoryUsageFast() +
1238 cfd_
->imm()->ApproximateUnflushedMemTablesMemoryUsage();
1242 bool InternalStats::HandleSizeAllMemTables(uint64_t* value
, DBImpl
* /*db*/,
1243 Version
* /*version*/) {
1244 // Using ApproximateMemoryUsageFast to avoid the need for synchronization
1245 *value
= cfd_
->mem()->ApproximateMemoryUsageFast() +
1246 cfd_
->imm()->ApproximateMemoryUsage();
1250 bool InternalStats::HandleNumEntriesActiveMemTable(uint64_t* value
,
1252 Version
* /*version*/) {
1253 // Current number of entires in the active memtable
1254 *value
= cfd_
->mem()->num_entries();
1258 bool InternalStats::HandleNumEntriesImmMemTables(uint64_t* value
,
1260 Version
* /*version*/) {
1261 // Current number of entries in the immutable memtables
1262 *value
= cfd_
->imm()->current()->GetTotalNumEntries();
1266 bool InternalStats::HandleNumDeletesActiveMemTable(uint64_t* value
,
1268 Version
* /*version*/) {
1269 // Current number of entires in the active memtable
1270 *value
= cfd_
->mem()->num_deletes();
1274 bool InternalStats::HandleNumDeletesImmMemTables(uint64_t* value
,
1276 Version
* /*version*/) {
1277 // Current number of entries in the immutable memtables
1278 *value
= cfd_
->imm()->current()->GetTotalNumDeletes();
1282 bool InternalStats::HandleEstimateNumKeys(uint64_t* value
, DBImpl
* /*db*/,
1283 Version
* /*version*/) {
1284 // Estimate number of entries in the column family:
1285 // Use estimated entries in tables + total entries in memtables.
1286 const auto* vstorage
= cfd_
->current()->storage_info();
1287 uint64_t estimate_keys
= cfd_
->mem()->num_entries() +
1288 cfd_
->imm()->current()->GetTotalNumEntries() +
1289 vstorage
->GetEstimatedActiveKeys();
1290 uint64_t estimate_deletes
=
1291 cfd_
->mem()->num_deletes() + cfd_
->imm()->current()->GetTotalNumDeletes();
1292 *value
= estimate_keys
> estimate_deletes
* 2
1293 ? estimate_keys
- (estimate_deletes
* 2)
1298 bool InternalStats::HandleNumSnapshots(uint64_t* value
, DBImpl
* db
,
1299 Version
* /*version*/) {
1300 *value
= db
->snapshots().count();
1304 bool InternalStats::HandleOldestSnapshotTime(uint64_t* value
, DBImpl
* db
,
1305 Version
* /*version*/) {
1306 *value
= static_cast<uint64_t>(db
->snapshots().GetOldestSnapshotTime());
1310 bool InternalStats::HandleOldestSnapshotSequence(uint64_t* value
, DBImpl
* db
,
1311 Version
* /*version*/) {
1312 *value
= static_cast<uint64_t>(db
->snapshots().GetOldestSnapshotSequence());
1316 bool InternalStats::HandleNumLiveVersions(uint64_t* value
, DBImpl
* /*db*/,
1317 Version
* /*version*/) {
1318 *value
= cfd_
->GetNumLiveVersions();
1322 bool InternalStats::HandleCurrentSuperVersionNumber(uint64_t* value
,
1324 Version
* /*version*/) {
1325 *value
= cfd_
->GetSuperVersionNumber();
1329 bool InternalStats::HandleIsFileDeletionsEnabled(uint64_t* value
, DBImpl
* db
,
1330 Version
* /*version*/) {
1331 *value
= db
->IsFileDeletionsEnabled() ? 1 : 0;
1335 bool InternalStats::HandleBaseLevel(uint64_t* value
, DBImpl
* /*db*/,
1336 Version
* /*version*/) {
1337 const auto* vstorage
= cfd_
->current()->storage_info();
1338 *value
= vstorage
->base_level();
1342 bool InternalStats::HandleTotalSstFilesSize(uint64_t* value
, DBImpl
* /*db*/,
1343 Version
* /*version*/) {
1344 *value
= cfd_
->GetTotalSstFilesSize();
1348 bool InternalStats::HandleLiveSstFilesSize(uint64_t* value
, DBImpl
* /*db*/,
1349 Version
* /*version*/) {
1350 *value
= cfd_
->GetLiveSstFilesSize();
1354 bool InternalStats::HandleEstimatePendingCompactionBytes(uint64_t* value
,
1356 Version
* /*version*/) {
1357 const auto* vstorage
= cfd_
->current()->storage_info();
1358 *value
= vstorage
->estimated_compaction_needed_bytes();
1362 bool InternalStats::HandleEstimateTableReadersMem(uint64_t* value
,
1365 *value
= (version
== nullptr) ? 0 : version
->GetMemoryUsageByTableReaders();
1369 bool InternalStats::HandleEstimateLiveDataSize(uint64_t* value
, DBImpl
* /*db*/,
1371 const auto* vstorage
= version
->storage_info();
1372 *value
= vstorage
->EstimateLiveDataSize();
1376 bool InternalStats::HandleMinLogNumberToKeep(uint64_t* value
, DBImpl
* db
,
1377 Version
* /*version*/) {
1378 *value
= db
->MinLogNumberToKeep();
1382 bool InternalStats::HandleMinObsoleteSstNumberToKeep(uint64_t* value
,
1384 Version
* /*version*/) {
1385 *value
= db
->MinObsoleteSstNumberToKeep();
1389 bool InternalStats::HandleActualDelayedWriteRate(uint64_t* value
, DBImpl
* db
,
1390 Version
* /*version*/) {
1391 const WriteController
& wc
= db
->write_controller();
1392 if (!wc
.NeedsDelay()) {
1395 *value
= wc
.delayed_write_rate();
1400 bool InternalStats::HandleIsWriteStopped(uint64_t* value
, DBImpl
* db
,
1401 Version
* /*version*/) {
1402 *value
= db
->write_controller().IsStopped() ? 1 : 0;
1406 bool InternalStats::HandleEstimateOldestKeyTime(uint64_t* value
, DBImpl
* /*db*/,
1407 Version
* /*version*/) {
1408 // TODO(yiwu): The property is currently available for fifo compaction
1409 // with allow_compaction = false. This is because we don't propagate
1410 // oldest_key_time on compaction.
1411 if (cfd_
->ioptions()->compaction_style
!= kCompactionStyleFIFO
||
1412 cfd_
->GetCurrentMutableCFOptions()
1413 ->compaction_options_fifo
.allow_compaction
) {
1417 TablePropertiesCollection collection
;
1418 auto s
= cfd_
->current()->GetPropertiesOfAllTables(&collection
);
1422 *value
= std::numeric_limits
<uint64_t>::max();
1423 for (auto& p
: collection
) {
1424 *value
= std::min(*value
, p
.second
->oldest_key_time
);
1430 *value
= std::min({cfd_
->mem()->ApproximateOldestKeyTime(),
1431 cfd_
->imm()->ApproximateOldestKeyTime(), *value
});
1433 return *value
> 0 && *value
< std::numeric_limits
<uint64_t>::max();
1436 Cache
* InternalStats::GetBlockCacheForStats() {
1437 auto* table_factory
= cfd_
->ioptions()->table_factory
.get();
1438 assert(table_factory
!= nullptr);
1439 return table_factory
->GetOptions
<Cache
>(TableFactory::kBlockCacheOpts());
1442 bool InternalStats::HandleBlockCacheCapacity(uint64_t* value
, DBImpl
* /*db*/,
1443 Version
* /*version*/) {
1444 Cache
* block_cache
= GetBlockCacheForStats();
1446 *value
= static_cast<uint64_t>(block_cache
->GetCapacity());
1452 bool InternalStats::HandleBlockCacheUsage(uint64_t* value
, DBImpl
* /*db*/,
1453 Version
* /*version*/) {
1454 Cache
* block_cache
= GetBlockCacheForStats();
1456 *value
= static_cast<uint64_t>(block_cache
->GetUsage());
1462 bool InternalStats::HandleBlockCachePinnedUsage(uint64_t* value
, DBImpl
* /*db*/,
1463 Version
* /*version*/) {
1464 Cache
* block_cache
= GetBlockCacheForStats();
1466 *value
= static_cast<uint64_t>(block_cache
->GetPinnedUsage());
1472 void InternalStats::DumpDBMapStats(
1473 std::map
<std::string
, std::string
>* db_stats
) {
1474 for (int i
= 0; i
< static_cast<int>(kIntStatsNumMax
); ++i
) {
1475 InternalDBStatsType type
= static_cast<InternalDBStatsType
>(i
);
1476 (*db_stats
)[db_stats_type_to_info
.at(type
).property_name
] =
1477 std::to_string(GetDBStats(type
));
1479 double seconds_up
= (clock_
->NowMicros() - started_at_
) / kMicrosInSec
;
1480 (*db_stats
)["db.uptime"] = std::to_string(seconds_up
);
1483 void InternalStats::DumpDBStats(std::string
* value
) {
1485 // DB-level stats, only available from default column family
1486 double seconds_up
= (clock_
->NowMicros() - started_at_
) / kMicrosInSec
;
1487 double interval_seconds_up
= seconds_up
- db_stats_snapshot_
.seconds_up
;
1488 snprintf(buf
, sizeof(buf
),
1489 "\n** DB Stats **\nUptime(secs): %.1f total, %.1f interval\n",
1490 seconds_up
, interval_seconds_up
);
1493 uint64_t user_bytes_written
=
1494 GetDBStats(InternalStats::kIntStatsBytesWritten
);
1495 uint64_t num_keys_written
=
1496 GetDBStats(InternalStats::kIntStatsNumKeysWritten
);
1497 uint64_t write_other
= GetDBStats(InternalStats::kIntStatsWriteDoneByOther
);
1498 uint64_t write_self
= GetDBStats(InternalStats::kIntStatsWriteDoneBySelf
);
1499 uint64_t wal_bytes
= GetDBStats(InternalStats::kIntStatsWalFileBytes
);
1500 uint64_t wal_synced
= GetDBStats(InternalStats::kIntStatsWalFileSynced
);
1501 uint64_t write_with_wal
= GetDBStats(InternalStats::kIntStatsWriteWithWal
);
1502 uint64_t write_stall_micros
=
1503 GetDBStats(InternalStats::kIntStatsWriteStallMicros
);
1505 const int kHumanMicrosLen
= 32;
1506 char human_micros
[kHumanMicrosLen
];
1509 // writes: total number of write requests.
1510 // keys: total number of key updates issued by all the write requests
1511 // commit groups: number of group commits issued to the DB. Each group can
1512 // contain one or more writes.
1513 // so writes/keys is the average number of put in multi-put or put
1514 // writes/groups is the average group commit size.
1516 // The format is the same for interval stats.
1517 snprintf(buf
, sizeof(buf
),
1518 "Cumulative writes: %s writes, %s keys, %s commit groups, "
1519 "%.1f writes per commit group, ingest: %.2f GB, %.2f MB/s\n",
1520 NumberToHumanString(write_other
+ write_self
).c_str(),
1521 NumberToHumanString(num_keys_written
).c_str(),
1522 NumberToHumanString(write_self
).c_str(),
1523 (write_other
+ write_self
) /
1524 std::max(1.0, static_cast<double>(write_self
)),
1525 user_bytes_written
/ kGB
,
1526 user_bytes_written
/ kMB
/ std::max(seconds_up
, 0.001));
1529 snprintf(buf
, sizeof(buf
),
1530 "Cumulative WAL: %s writes, %s syncs, "
1531 "%.2f writes per sync, written: %.2f GB, %.2f MB/s\n",
1532 NumberToHumanString(write_with_wal
).c_str(),
1533 NumberToHumanString(wal_synced
).c_str(),
1534 write_with_wal
/ std::max(1.0, static_cast<double>(wal_synced
)),
1535 wal_bytes
/ kGB
, wal_bytes
/ kMB
/ std::max(seconds_up
, 0.001));
1538 AppendHumanMicros(write_stall_micros
, human_micros
, kHumanMicrosLen
, true);
1539 snprintf(buf
, sizeof(buf
), "Cumulative stall: %s, %.1f percent\n",
1541 // 10000 = divide by 1M to get secs, then multiply by 100 for pct
1542 write_stall_micros
/ 10000.0 / std::max(seconds_up
, 0.001));
1546 uint64_t interval_write_other
= write_other
- db_stats_snapshot_
.write_other
;
1547 uint64_t interval_write_self
= write_self
- db_stats_snapshot_
.write_self
;
1548 uint64_t interval_num_keys_written
=
1549 num_keys_written
- db_stats_snapshot_
.num_keys_written
;
1552 "Interval writes: %s writes, %s keys, %s commit groups, "
1553 "%.1f writes per commit group, ingest: %.2f MB, %.2f MB/s\n",
1554 NumberToHumanString(interval_write_other
+ interval_write_self
).c_str(),
1555 NumberToHumanString(interval_num_keys_written
).c_str(),
1556 NumberToHumanString(interval_write_self
).c_str(),
1557 static_cast<double>(interval_write_other
+ interval_write_self
) /
1558 std::max(1.0, static_cast<double>(interval_write_self
)),
1559 (user_bytes_written
- db_stats_snapshot_
.ingest_bytes
) / kMB
,
1560 (user_bytes_written
- db_stats_snapshot_
.ingest_bytes
) / kMB
/
1561 std::max(interval_seconds_up
, 0.001)),
1564 uint64_t interval_write_with_wal
=
1565 write_with_wal
- db_stats_snapshot_
.write_with_wal
;
1566 uint64_t interval_wal_synced
= wal_synced
- db_stats_snapshot_
.wal_synced
;
1567 uint64_t interval_wal_bytes
= wal_bytes
- db_stats_snapshot_
.wal_bytes
;
1569 snprintf(buf
, sizeof(buf
),
1570 "Interval WAL: %s writes, %s syncs, "
1571 "%.2f writes per sync, written: %.2f GB, %.2f MB/s\n",
1572 NumberToHumanString(interval_write_with_wal
).c_str(),
1573 NumberToHumanString(interval_wal_synced
).c_str(),
1574 interval_write_with_wal
/
1575 std::max(1.0, static_cast<double>(interval_wal_synced
)),
1576 interval_wal_bytes
/ kGB
,
1577 interval_wal_bytes
/ kMB
/ std::max(interval_seconds_up
, 0.001));
1581 AppendHumanMicros(write_stall_micros
- db_stats_snapshot_
.write_stall_micros
,
1582 human_micros
, kHumanMicrosLen
, true);
1583 snprintf(buf
, sizeof(buf
), "Interval stall: %s, %.1f percent\n", human_micros
,
1584 // 10000 = divide by 1M to get secs, then multiply by 100 for pct
1585 (write_stall_micros
- db_stats_snapshot_
.write_stall_micros
) /
1586 10000.0 / std::max(interval_seconds_up
, 0.001));
1589 db_stats_snapshot_
.seconds_up
= seconds_up
;
1590 db_stats_snapshot_
.ingest_bytes
= user_bytes_written
;
1591 db_stats_snapshot_
.write_other
= write_other
;
1592 db_stats_snapshot_
.write_self
= write_self
;
1593 db_stats_snapshot_
.num_keys_written
= num_keys_written
;
1594 db_stats_snapshot_
.wal_bytes
= wal_bytes
;
1595 db_stats_snapshot_
.wal_synced
= wal_synced
;
1596 db_stats_snapshot_
.write_with_wal
= write_with_wal
;
1597 db_stats_snapshot_
.write_stall_micros
= write_stall_micros
;
1601 * Dump Compaction Level stats to a map of stat name with "compaction." prefix
1602 * to value in double as string. The level in stat name is represented with
1603 * a prefix "Lx" where "x" is the level number. A special level "Sum"
1604 * represents the sum of a stat for all levels.
1605 * The result also contains IO stall counters which keys start with "io_stalls."
1606 * and values represent uint64 encoded as strings.
1608 void InternalStats::DumpCFMapStats(
1609 std::map
<std::string
, std::string
>* cf_stats
) {
1610 const VersionStorageInfo
* vstorage
= cfd_
->current()->storage_info();
1611 CompactionStats compaction_stats_sum
;
1612 std::map
<int, std::map
<LevelStatType
, double>> levels_stats
;
1613 DumpCFMapStats(vstorage
, &levels_stats
, &compaction_stats_sum
);
1614 for (auto const& level_ent
: levels_stats
) {
1616 level_ent
.first
== -1 ? "Sum" : "L" + std::to_string(level_ent
.first
);
1617 for (auto const& stat_ent
: level_ent
.second
) {
1618 auto stat_type
= stat_ent
.first
;
1620 "compaction." + level_str
+ "." +
1621 InternalStats::compaction_level_stats
.at(stat_type
).property_name
;
1622 (*cf_stats
)[key_str
] = std::to_string(stat_ent
.second
);
1626 DumpCFMapStatsIOStalls(cf_stats
);
1629 void InternalStats::DumpCFMapStats(
1630 const VersionStorageInfo
* vstorage
,
1631 std::map
<int, std::map
<LevelStatType
, double>>* levels_stats
,
1632 CompactionStats
* compaction_stats_sum
) {
1635 int num_levels_to_check
=
1636 (cfd_
->ioptions()->compaction_style
!= kCompactionStyleFIFO
)
1637 ? vstorage
->num_levels() - 1
1640 // Compaction scores are sorted based on its value. Restore them to the
1642 std::vector
<double> compaction_score(number_levels_
, 0);
1643 for (int i
= 0; i
< num_levels_to_check
; ++i
) {
1644 compaction_score
[vstorage
->CompactionScoreLevel(i
)] =
1645 vstorage
->CompactionScore(i
);
1647 // Count # of files being compacted for each level
1648 std::vector
<int> files_being_compacted(number_levels_
, 0);
1649 for (int level
= 0; level
< number_levels_
; ++level
) {
1650 for (auto* f
: vstorage
->LevelFiles(level
)) {
1651 if (f
->being_compacted
) {
1652 ++files_being_compacted
[level
];
1657 int total_files
= 0;
1658 int total_files_being_compacted
= 0;
1659 double total_file_size
= 0;
1660 uint64_t flush_ingest
= cf_stats_value_
[BYTES_FLUSHED
];
1661 uint64_t add_file_ingest
= cf_stats_value_
[BYTES_INGESTED_ADD_FILE
];
1662 uint64_t curr_ingest
= flush_ingest
+ add_file_ingest
;
1663 for (int level
= 0; level
< number_levels_
; level
++) {
1664 int files
= vstorage
->NumLevelFiles(level
);
1665 total_files
+= files
;
1666 total_files_being_compacted
+= files_being_compacted
[level
];
1667 if (comp_stats_
[level
].micros
> 0 || comp_stats_
[level
].cpu_micros
> 0 ||
1669 compaction_stats_sum
->Add(comp_stats_
[level
]);
1670 total_file_size
+= vstorage
->NumLevelBytes(level
);
1671 uint64_t input_bytes
;
1673 input_bytes
= curr_ingest
;
1675 input_bytes
= comp_stats_
[level
].bytes_read_non_output_levels
+
1676 comp_stats_
[level
].bytes_read_blob
;
1681 : static_cast<double>(comp_stats_
[level
].bytes_written
+
1682 comp_stats_
[level
].bytes_written_blob
) /
1684 std::map
<LevelStatType
, double> level_stats
;
1685 PrepareLevelStats(&level_stats
, files
, files_being_compacted
[level
],
1686 static_cast<double>(vstorage
->NumLevelBytes(level
)),
1687 compaction_score
[level
], w_amp
, comp_stats_
[level
]);
1688 (*levels_stats
)[level
] = level_stats
;
1691 // Cumulative summary
1692 double w_amp
= (0 == curr_ingest
)
1694 : (compaction_stats_sum
->bytes_written
+
1695 compaction_stats_sum
->bytes_written_blob
) /
1696 static_cast<double>(curr_ingest
);
1697 // Stats summary across levels
1698 std::map
<LevelStatType
, double> sum_stats
;
1699 PrepareLevelStats(&sum_stats
, total_files
, total_files_being_compacted
,
1700 total_file_size
, 0, w_amp
, *compaction_stats_sum
);
1701 (*levels_stats
)[-1] = sum_stats
; // -1 is for the Sum level
1704 void InternalStats::DumpCFMapStatsByPriority(
1705 std::map
<int, std::map
<LevelStatType
, double>>* priorities_stats
) {
1706 for (size_t priority
= 0; priority
< comp_stats_by_pri_
.size(); priority
++) {
1707 if (comp_stats_by_pri_
[priority
].micros
> 0) {
1708 std::map
<LevelStatType
, double> priority_stats
;
1709 PrepareLevelStats(&priority_stats
, 0 /* num_files */,
1710 0 /* being_compacted */, 0 /* total_file_size */,
1711 0 /* compaction_score */, 0 /* w_amp */,
1712 comp_stats_by_pri_
[priority
]);
1713 (*priorities_stats
)[static_cast<int>(priority
)] = priority_stats
;
1718 void InternalStats::DumpCFMapStatsIOStalls(
1719 std::map
<std::string
, std::string
>* cf_stats
) {
1720 (*cf_stats
)["io_stalls.level0_slowdown"] =
1721 std::to_string(cf_stats_count_
[L0_FILE_COUNT_LIMIT_SLOWDOWNS
]);
1722 (*cf_stats
)["io_stalls.level0_slowdown_with_compaction"] =
1723 std::to_string(cf_stats_count_
[LOCKED_L0_FILE_COUNT_LIMIT_SLOWDOWNS
]);
1724 (*cf_stats
)["io_stalls.level0_numfiles"] =
1725 std::to_string(cf_stats_count_
[L0_FILE_COUNT_LIMIT_STOPS
]);
1726 (*cf_stats
)["io_stalls.level0_numfiles_with_compaction"] =
1727 std::to_string(cf_stats_count_
[LOCKED_L0_FILE_COUNT_LIMIT_STOPS
]);
1728 (*cf_stats
)["io_stalls.stop_for_pending_compaction_bytes"] =
1729 std::to_string(cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_STOPS
]);
1730 (*cf_stats
)["io_stalls.slowdown_for_pending_compaction_bytes"] =
1731 std::to_string(cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_SLOWDOWNS
]);
1732 (*cf_stats
)["io_stalls.memtable_compaction"] =
1733 std::to_string(cf_stats_count_
[MEMTABLE_LIMIT_STOPS
]);
1734 (*cf_stats
)["io_stalls.memtable_slowdown"] =
1735 std::to_string(cf_stats_count_
[MEMTABLE_LIMIT_SLOWDOWNS
]);
1737 uint64_t total_stop
= cf_stats_count_
[L0_FILE_COUNT_LIMIT_STOPS
] +
1738 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_STOPS
] +
1739 cf_stats_count_
[MEMTABLE_LIMIT_STOPS
];
1741 uint64_t total_slowdown
=
1742 cf_stats_count_
[L0_FILE_COUNT_LIMIT_SLOWDOWNS
] +
1743 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_SLOWDOWNS
] +
1744 cf_stats_count_
[MEMTABLE_LIMIT_SLOWDOWNS
];
1746 (*cf_stats
)["io_stalls.total_stop"] = std::to_string(total_stop
);
1747 (*cf_stats
)["io_stalls.total_slowdown"] = std::to_string(total_slowdown
);
1750 void InternalStats::DumpCFStats(std::string
* value
) {
1751 DumpCFStatsNoFileHistogram(/*is_periodic=*/false, value
);
1752 DumpCFFileHistogram(value
);
1755 void InternalStats::DumpCFStatsNoFileHistogram(bool is_periodic
,
1756 std::string
* value
) {
1758 // Per-ColumnFamily stats
1759 PrintLevelStatsHeader(buf
, sizeof(buf
), cfd_
->GetName(), "Level");
1762 // Print stats for each level
1763 const VersionStorageInfo
* vstorage
= cfd_
->current()->storage_info();
1764 std::map
<int, std::map
<LevelStatType
, double>> levels_stats
;
1765 CompactionStats compaction_stats_sum
;
1766 DumpCFMapStats(vstorage
, &levels_stats
, &compaction_stats_sum
);
1767 for (int l
= 0; l
< number_levels_
; ++l
) {
1768 if (levels_stats
.find(l
) != levels_stats
.end()) {
1769 PrintLevelStats(buf
, sizeof(buf
), "L" + std::to_string(l
),
1775 // Print sum of level stats
1776 PrintLevelStats(buf
, sizeof(buf
), "Sum", levels_stats
[-1]);
1779 uint64_t flush_ingest
= cf_stats_value_
[BYTES_FLUSHED
];
1780 uint64_t add_file_ingest
= cf_stats_value_
[BYTES_INGESTED_ADD_FILE
];
1781 uint64_t ingest_files_addfile
= cf_stats_value_
[INGESTED_NUM_FILES_TOTAL
];
1782 uint64_t ingest_l0_files_addfile
=
1783 cf_stats_value_
[INGESTED_LEVEL0_NUM_FILES_TOTAL
];
1784 uint64_t ingest_keys_addfile
= cf_stats_value_
[INGESTED_NUM_KEYS_TOTAL
];
1785 // Cumulative summary
1786 uint64_t total_stall_count
=
1787 cf_stats_count_
[L0_FILE_COUNT_LIMIT_SLOWDOWNS
] +
1788 cf_stats_count_
[L0_FILE_COUNT_LIMIT_STOPS
] +
1789 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_SLOWDOWNS
] +
1790 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_STOPS
] +
1791 cf_stats_count_
[MEMTABLE_LIMIT_STOPS
] +
1792 cf_stats_count_
[MEMTABLE_LIMIT_SLOWDOWNS
];
1794 uint64_t interval_flush_ingest
=
1795 flush_ingest
- cf_stats_snapshot_
.ingest_bytes_flush
;
1796 uint64_t interval_add_file_inget
=
1797 add_file_ingest
- cf_stats_snapshot_
.ingest_bytes_addfile
;
1798 uint64_t interval_ingest
=
1799 interval_flush_ingest
+ interval_add_file_inget
+ 1;
1800 CompactionStats
interval_stats(compaction_stats_sum
);
1801 interval_stats
.Subtract(cf_stats_snapshot_
.comp_stats
);
1803 (interval_stats
.bytes_written
+ interval_stats
.bytes_written_blob
) /
1804 static_cast<double>(interval_ingest
);
1805 PrintLevelStats(buf
, sizeof(buf
), "Int", 0, 0, 0, 0, w_amp
, interval_stats
);
1808 PrintLevelStatsHeader(buf
, sizeof(buf
), cfd_
->GetName(), "Priority");
1810 std::map
<int, std::map
<LevelStatType
, double>> priorities_stats
;
1811 DumpCFMapStatsByPriority(&priorities_stats
);
1812 for (size_t priority
= 0; priority
< comp_stats_by_pri_
.size(); ++priority
) {
1813 if (priorities_stats
.find(static_cast<int>(priority
)) !=
1814 priorities_stats
.end()) {
1817 Env::PriorityToString(static_cast<Env::Priority
>(priority
)),
1818 priorities_stats
[static_cast<int>(priority
)]);
1823 const auto blob_st
= vstorage
->GetBlobStats();
1825 snprintf(buf
, sizeof(buf
),
1826 "\nBlob file count: %" ROCKSDB_PRIszt
1827 ", total size: %.1f GB, garbage size: %.1f GB, space amp: %.1f\n\n",
1828 vstorage
->GetBlobFiles().size(), blob_st
.total_file_size
/ kGB
,
1829 blob_st
.total_garbage_size
/ kGB
, blob_st
.space_amp
);
1832 uint64_t now_micros
= clock_
->NowMicros();
1833 double seconds_up
= (now_micros
- started_at_
) / kMicrosInSec
;
1834 double interval_seconds_up
= seconds_up
- cf_stats_snapshot_
.seconds_up
;
1835 snprintf(buf
, sizeof(buf
), "Uptime(secs): %.1f total, %.1f interval\n",
1836 seconds_up
, interval_seconds_up
);
1838 snprintf(buf
, sizeof(buf
), "Flush(GB): cumulative %.3f, interval %.3f\n",
1839 flush_ingest
/ kGB
, interval_flush_ingest
/ kGB
);
1841 snprintf(buf
, sizeof(buf
), "AddFile(GB): cumulative %.3f, interval %.3f\n",
1842 add_file_ingest
/ kGB
, interval_add_file_inget
/ kGB
);
1845 uint64_t interval_ingest_files_addfile
=
1846 ingest_files_addfile
- cf_stats_snapshot_
.ingest_files_addfile
;
1847 snprintf(buf
, sizeof(buf
),
1848 "AddFile(Total Files): cumulative %" PRIu64
", interval %" PRIu64
1850 ingest_files_addfile
, interval_ingest_files_addfile
);
1853 uint64_t interval_ingest_l0_files_addfile
=
1854 ingest_l0_files_addfile
- cf_stats_snapshot_
.ingest_l0_files_addfile
;
1855 snprintf(buf
, sizeof(buf
),
1856 "AddFile(L0 Files): cumulative %" PRIu64
", interval %" PRIu64
"\n",
1857 ingest_l0_files_addfile
, interval_ingest_l0_files_addfile
);
1860 uint64_t interval_ingest_keys_addfile
=
1861 ingest_keys_addfile
- cf_stats_snapshot_
.ingest_keys_addfile
;
1862 snprintf(buf
, sizeof(buf
),
1863 "AddFile(Keys): cumulative %" PRIu64
", interval %" PRIu64
"\n",
1864 ingest_keys_addfile
, interval_ingest_keys_addfile
);
1868 uint64_t compact_bytes_read
= 0;
1869 uint64_t compact_bytes_write
= 0;
1870 uint64_t compact_micros
= 0;
1871 for (int level
= 0; level
< number_levels_
; level
++) {
1872 compact_bytes_read
+= comp_stats_
[level
].bytes_read_output_level
+
1873 comp_stats_
[level
].bytes_read_non_output_levels
+
1874 comp_stats_
[level
].bytes_read_blob
;
1875 compact_bytes_write
+= comp_stats_
[level
].bytes_written
+
1876 comp_stats_
[level
].bytes_written_blob
;
1877 compact_micros
+= comp_stats_
[level
].micros
;
1880 snprintf(buf
, sizeof(buf
),
1881 "Cumulative compaction: %.2f GB write, %.2f MB/s write, "
1882 "%.2f GB read, %.2f MB/s read, %.1f seconds\n",
1883 compact_bytes_write
/ kGB
,
1884 compact_bytes_write
/ kMB
/ std::max(seconds_up
, 0.001),
1885 compact_bytes_read
/ kGB
,
1886 compact_bytes_read
/ kMB
/ std::max(seconds_up
, 0.001),
1887 compact_micros
/ kMicrosInSec
);
1890 // Compaction interval
1891 uint64_t interval_compact_bytes_write
=
1892 compact_bytes_write
- cf_stats_snapshot_
.compact_bytes_write
;
1893 uint64_t interval_compact_bytes_read
=
1894 compact_bytes_read
- cf_stats_snapshot_
.compact_bytes_read
;
1895 uint64_t interval_compact_micros
=
1896 compact_micros
- cf_stats_snapshot_
.compact_micros
;
1900 "Interval compaction: %.2f GB write, %.2f MB/s write, "
1901 "%.2f GB read, %.2f MB/s read, %.1f seconds\n",
1902 interval_compact_bytes_write
/ kGB
,
1903 interval_compact_bytes_write
/ kMB
/ std::max(interval_seconds_up
, 0.001),
1904 interval_compact_bytes_read
/ kGB
,
1905 interval_compact_bytes_read
/ kMB
/ std::max(interval_seconds_up
, 0.001),
1906 interval_compact_micros
/ kMicrosInSec
);
1909 cf_stats_snapshot_
.compact_bytes_write
= compact_bytes_write
;
1910 cf_stats_snapshot_
.compact_bytes_read
= compact_bytes_read
;
1911 cf_stats_snapshot_
.compact_micros
= compact_micros
;
1914 snprintf(buf
, sizeof(buf
),
1915 "Stalls(count): %" PRIu64
1916 " level0_slowdown, "
1918 " level0_slowdown_with_compaction, "
1920 " level0_numfiles, "
1922 " level0_numfiles_with_compaction, "
1924 " stop for pending_compaction_bytes, "
1926 " slowdown for pending_compaction_bytes, "
1928 " memtable_compaction, "
1930 " memtable_slowdown, "
1931 "interval %" PRIu64
" total count\n",
1932 cf_stats_count_
[L0_FILE_COUNT_LIMIT_SLOWDOWNS
],
1933 cf_stats_count_
[LOCKED_L0_FILE_COUNT_LIMIT_SLOWDOWNS
],
1934 cf_stats_count_
[L0_FILE_COUNT_LIMIT_STOPS
],
1935 cf_stats_count_
[LOCKED_L0_FILE_COUNT_LIMIT_STOPS
],
1936 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_STOPS
],
1937 cf_stats_count_
[PENDING_COMPACTION_BYTES_LIMIT_SLOWDOWNS
],
1938 cf_stats_count_
[MEMTABLE_LIMIT_STOPS
],
1939 cf_stats_count_
[MEMTABLE_LIMIT_SLOWDOWNS
],
1940 total_stall_count
- cf_stats_snapshot_
.stall_count
);
1944 cf_stats_snapshot_
.seconds_up
= seconds_up
;
1945 cf_stats_snapshot_
.ingest_bytes_flush
= flush_ingest
;
1946 cf_stats_snapshot_
.ingest_bytes_addfile
= add_file_ingest
;
1947 cf_stats_snapshot_
.ingest_files_addfile
= ingest_files_addfile
;
1948 cf_stats_snapshot_
.ingest_l0_files_addfile
= ingest_l0_files_addfile
;
1949 cf_stats_snapshot_
.ingest_keys_addfile
= ingest_keys_addfile
;
1950 cf_stats_snapshot_
.comp_stats
= compaction_stats_sum
;
1951 cf_stats_snapshot_
.stall_count
= total_stall_count
;
1954 // Do not gather cache entry stats during CFStats because DB
1955 // mutex is held. Only dump last cached collection (rely on DB
1956 // periodic stats dump to update)
1957 if (cache_entry_stats_collector_
) {
1958 CacheEntryRoleStats stats
;
1960 cache_entry_stats_collector_
->GetStats(&stats
);
1962 constexpr uint64_t kDayInMicros
= uint64_t{86400} * 1000000U;
1964 // Skip if stats are extremely old (> 1 day, incl not yet populated)
1965 if (now_micros
- stats
.last_end_time_micros_
< kDayInMicros
) {
1966 value
->append(stats
.ToString(clock_
));
1971 void InternalStats::DumpCFFileHistogram(std::string
* value
) {
1975 std::ostringstream oss
;
1976 oss
<< "\n** File Read Latency Histogram By Level [" << cfd_
->GetName()
1979 for (int level
= 0; level
< number_levels_
; level
++) {
1980 if (!file_read_latency_
[level
].Empty()) {
1981 oss
<< "** Level " << level
<< " read latency histogram (micros):\n"
1982 << file_read_latency_
[level
].ToString() << '\n';
1986 if (!blob_file_read_latency_
.Empty()) {
1987 oss
<< "** Blob file read latency histogram (micros):\n"
1988 << blob_file_read_latency_
.ToString() << '\n';
1991 value
->append(oss
.str());
1996 const DBPropertyInfo
* GetPropertyInfo(const Slice
& /*property*/) {
2000 #endif // !ROCKSDB_LITE
2002 } // namespace ROCKSDB_NAMESPACE