Skip to content

Commit c913b6d

Browse files
authored
rocksdb usage - Replace Column Size with more accurate Total Size (#6540)
Add rocksdb x-stats command to print various stats for each column family --------- Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
1 parent de9b301 commit c913b6d

File tree

5 files changed

+266
-32
lines changed

5 files changed

+266
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
- Support for `shanghaiTime` fork and Shanghai EVM smart contracts in QBFT/IBFT chains [#6353](https://github.com/hyperledger/besu/pull/6353)
3131
- Change ExecutionHaltReason for contract creation collision case to return ILLEGAL_STATE_CHANGE [#6518](https://github.com/hyperledger/besu/pull/6518)
3232
- Experimental feature `--Xbonsai-code-using-code-hash-enabled` for storing Bonsai code storage by code hash [#6505](https://github.com/hyperledger/besu/pull/6505)
33+
- More accurate column size `storage rocksdb usage` subcommand [#6540](https://github.com/hyperledger/besu/pull/6540)
34+
- Adds `storage rocksdb x-stats` subcommand [#6540](https://github.com/hyperledger/besu/pull/6540)
3335

3436
### Bug fixes
3537
- Fix the way an advertised host configured with `--p2p-host` is treated when communicating with the originator of a PING packet [#6225](https://github.com/hyperledger/besu/pull/6225)

besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbHelper.java

Lines changed: 201 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ArrayList;
2222
import java.util.List;
2323
import java.util.function.BiConsumer;
24+
import java.util.stream.Stream;
2425

2526
import org.bouncycastle.util.Arrays;
2627
import org.rocksdb.ColumnFamilyDescriptor;
@@ -66,36 +67,210 @@ static void forEachColumnFamily(
6667
}
6768
}
6869

69-
static void printUsageForColumnFamily(
70+
static void printStatsForColumnFamily(
7071
final RocksDB rocksdb, final ColumnFamilyHandle cfHandle, final PrintWriter out)
71-
throws RocksDBException, NumberFormatException {
72+
throws RocksDBException {
7273
final String size = rocksdb.getProperty(cfHandle, "rocksdb.estimate-live-data-size");
7374
final String numberOfKeys = rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys");
74-
boolean emptyColumnFamily = false;
75-
if (!size.isBlank() && !numberOfKeys.isBlank()) {
75+
final long sizeLong = Long.parseLong(size);
76+
final long numberOfKeysLong = Long.parseLong(numberOfKeys);
77+
if (!size.isBlank()
78+
&& !numberOfKeys.isBlank()
79+
&& isPopulatedColumnFamily(sizeLong, numberOfKeysLong)) {
80+
out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
81+
out.println("Column Family: " + getNameById(cfHandle.getName()));
82+
83+
final String prefix = "rocksdb.";
84+
final String cfstats = "cfstats";
85+
final String cfstats_no_file_histogram = "cfstats-no-file-histogram";
86+
final String cf_file_histogram = "cf-file-histogram";
87+
final String cf_write_stall_stats = "cf-write-stall-stats";
88+
final String dbstats = "dbstats";
89+
final String db_write_stall_stats = "db-write-stall-stats";
90+
final String levelstats = "levelstats";
91+
final String block_cache_entry_stats = "block-cache-entry-stats";
92+
final String fast_block_cache_entry_stats = "fast-block-cache-entry-stats";
93+
final String num_immutable_mem_table = "num-immutable-mem-table";
94+
final String num_immutable_mem_table_flushed = "num-immutable-mem-table-flushed";
95+
final String mem_table_flush_pending = "mem-table-flush-pending";
96+
final String compaction_pending = "compaction-pending";
97+
final String background_errors = "background-errors";
98+
final String cur_size_active_mem_table = "cur-size-active-mem-table";
99+
final String cur_size_all_mem_tables = "cur-size-all-mem-tables";
100+
final String size_all_mem_tables = "size-all-mem-tables";
101+
final String num_entries_active_mem_table = "num-entries-active-mem-table";
102+
final String num_entries_imm_mem_tables = "num-entries-imm-mem-tables";
103+
final String num_deletes_active_mem_table = "num-deletes-active-mem-table";
104+
final String num_deletes_imm_mem_tables = "num-deletes-imm-mem-tables";
105+
final String estimate_num_keys = "estimate-num-keys";
106+
final String estimate_table_readers_mem = "estimate-table-readers-mem";
107+
final String is_file_deletions_enabled = "is-file-deletions-enabled";
108+
final String num_snapshots = "num-snapshots";
109+
final String oldest_snapshot_time = "oldest-snapshot-time";
110+
final String oldest_snapshot_sequence = "oldest-snapshot-sequence";
111+
final String num_live_versions = "num-live-versions";
112+
final String current_version_number = "current-super-version-number";
113+
final String estimate_live_data_size = "estimate-live-data-size";
114+
final String min_log_number_to_keep_str = "min-log-number-to-keep";
115+
final String min_obsolete_sst_number_to_keep_str = "min-obsolete-sst-number-to-keep";
116+
final String base_level_str = "base-level";
117+
final String total_sst_files_size = "total-sst-files-size";
118+
final String live_sst_files_size = "live-sst-files-size";
119+
final String obsolete_sst_files_size = "obsolete-sst-files-size";
120+
final String live_sst_files_size_at_temperature = "live-sst-files-size-at-temperature";
121+
final String estimate_pending_comp_bytes = "estimate-pending-compaction-bytes";
122+
final String aggregated_table_properties = "aggregated-table-properties";
123+
final String num_running_compactions = "num-running-compactions";
124+
final String num_running_flushes = "num-running-flushes";
125+
final String actual_delayed_write_rate = "actual-delayed-write-rate";
126+
final String is_write_stopped = "is-write-stopped";
127+
final String estimate_oldest_key_time = "estimate-oldest-key-time";
128+
final String block_cache_capacity = "block-cache-capacity";
129+
final String block_cache_usage = "block-cache-usage";
130+
final String block_cache_pinned_usage = "block-cache-pinned-usage";
131+
final String options_statistics = "options-statistics";
132+
final String num_blob_files = "num-blob-files";
133+
final String blob_stats = "blob-stats";
134+
final String total_blob_file_size = "total-blob-file-size";
135+
final String live_blob_file_size = "live-blob-file-size";
136+
final String live_blob_file_garbage_size = "live-blob-file-garbage-size";
137+
final String blob_cache_capacity = "blob-cache-capacity";
138+
final String blob_cache_usage = "blob-cache-usage";
139+
final String blob_cache_pinned_usage = "blob-cache-pinned-usage";
140+
Stream.of(
141+
cfstats,
142+
cfstats_no_file_histogram,
143+
cf_file_histogram,
144+
cf_write_stall_stats,
145+
dbstats,
146+
db_write_stall_stats,
147+
levelstats,
148+
block_cache_entry_stats,
149+
fast_block_cache_entry_stats,
150+
num_immutable_mem_table,
151+
num_immutable_mem_table_flushed,
152+
mem_table_flush_pending,
153+
compaction_pending,
154+
background_errors,
155+
cur_size_active_mem_table,
156+
cur_size_all_mem_tables,
157+
size_all_mem_tables,
158+
num_entries_active_mem_table,
159+
num_entries_imm_mem_tables,
160+
num_deletes_active_mem_table,
161+
num_deletes_imm_mem_tables,
162+
estimate_num_keys,
163+
estimate_table_readers_mem,
164+
is_file_deletions_enabled,
165+
num_snapshots,
166+
oldest_snapshot_time,
167+
oldest_snapshot_sequence,
168+
num_live_versions,
169+
current_version_number,
170+
estimate_live_data_size,
171+
min_log_number_to_keep_str,
172+
min_obsolete_sst_number_to_keep_str,
173+
base_level_str,
174+
total_sst_files_size,
175+
live_sst_files_size,
176+
obsolete_sst_files_size,
177+
live_sst_files_size_at_temperature,
178+
estimate_pending_comp_bytes,
179+
aggregated_table_properties,
180+
num_running_compactions,
181+
num_running_flushes,
182+
actual_delayed_write_rate,
183+
is_write_stopped,
184+
estimate_oldest_key_time,
185+
block_cache_capacity,
186+
block_cache_usage,
187+
block_cache_pinned_usage,
188+
options_statistics,
189+
num_blob_files,
190+
blob_stats,
191+
total_blob_file_size,
192+
live_blob_file_size,
193+
live_blob_file_garbage_size,
194+
blob_cache_capacity,
195+
blob_cache_usage,
196+
blob_cache_pinned_usage)
197+
.forEach(
198+
prop -> {
199+
try {
200+
final String value = rocksdb.getProperty(cfHandle, prefix + prop);
201+
if (!value.isBlank()) {
202+
out.println(prop + ": " + value);
203+
}
204+
} catch (RocksDBException e) {
205+
LOG.debug("couldn't get property {}", prop);
206+
}
207+
});
208+
out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
209+
}
210+
}
211+
212+
static ColumnFamilyUsage getAndPrintUsageForColumnFamily(
213+
final RocksDB rocksdb, final ColumnFamilyHandle cfHandle, final PrintWriter out)
214+
throws RocksDBException, NumberFormatException {
215+
final String numberOfKeys = rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys");
216+
if (!numberOfKeys.isBlank()) {
76217
try {
77-
final long sizeLong = Long.parseLong(size);
78218
final long numberOfKeysLong = Long.parseLong(numberOfKeys);
79219
final String totalSstFilesSize =
80220
rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size");
81221
final long totalSstFilesSizeLong =
82222
!totalSstFilesSize.isBlank() ? Long.parseLong(totalSstFilesSize) : 0;
83-
if (sizeLong == 0 && numberOfKeysLong == 0) {
84-
emptyColumnFamily = true;
85-
}
86223

87-
if (!emptyColumnFamily) {
224+
final String totalBlobFilesSize =
225+
rocksdb.getProperty(cfHandle, "rocksdb.total-blob-file-size");
226+
final long totalBlobFilesSizeLong =
227+
!totalBlobFilesSize.isBlank() ? Long.parseLong(totalBlobFilesSize) : 0;
228+
229+
final long totalFilesSize = totalSstFilesSizeLong + totalBlobFilesSizeLong;
230+
if (isPopulatedColumnFamily(0, numberOfKeysLong)) {
88231
printLine(
89232
out,
90233
getNameById(cfHandle.getName()),
91234
rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys"),
92-
formatOutputSize(sizeLong),
93-
formatOutputSize(totalSstFilesSizeLong));
235+
formatOutputSize(totalFilesSize),
236+
formatOutputSize(totalSstFilesSizeLong),
237+
formatOutputSize(totalBlobFilesSizeLong));
94238
}
239+
return new ColumnFamilyUsage(
240+
getNameById(cfHandle.getName()),
241+
numberOfKeysLong,
242+
totalFilesSize,
243+
totalSstFilesSizeLong,
244+
totalBlobFilesSizeLong);
95245
} catch (NumberFormatException e) {
96246
LOG.error("Failed to parse string into long: " + e.getMessage());
97247
}
98248
}
249+
// return empty usage on error
250+
return new ColumnFamilyUsage(getNameById(cfHandle.getName()), 0, 0, 0, 0);
251+
}
252+
253+
static void printTotals(final PrintWriter out, final List<ColumnFamilyUsage> columnFamilyUsages) {
254+
final long totalKeys = columnFamilyUsages.stream().mapToLong(ColumnFamilyUsage::keys).sum();
255+
final long totalSize =
256+
columnFamilyUsages.stream().mapToLong(ColumnFamilyUsage::totalSize).sum();
257+
final long totalSsts =
258+
columnFamilyUsages.stream().mapToLong(ColumnFamilyUsage::sstFilesSize).sum();
259+
final long totalBlobs =
260+
columnFamilyUsages.stream().mapToLong(ColumnFamilyUsage::blobFilesSize).sum();
261+
printSeparator(out);
262+
printLine(
263+
out,
264+
"ESTIMATED TOTAL",
265+
String.valueOf(totalKeys),
266+
formatOutputSize(totalSize),
267+
formatOutputSize(totalSsts),
268+
formatOutputSize(totalBlobs));
269+
printSeparator(out);
270+
}
271+
272+
private static boolean isPopulatedColumnFamily(final long size, final long numberOfKeys) {
273+
return size != 0 || numberOfKeys != 0;
99274
}
100275

101276
static String formatOutputSize(final long size) {
@@ -123,19 +298,28 @@ private static String getNameById(final byte[] id) {
123298
}
124299

125300
static void printTableHeader(final PrintWriter out) {
301+
printSeparator(out);
126302
out.format(
127-
"| Column Family | Keys | Column Size | SST Files Size |\n");
303+
"| Column Family | Keys | Total Size | SST Files Size | Blob Files Size | \n");
304+
printSeparator(out);
305+
}
306+
307+
private static void printSeparator(final PrintWriter out) {
128308
out.format(
129-
"|--------------------------------|-----------------|--------------|-----------------|\n");
309+
"|--------------------------------|-----------------|-------------|-----------------|------------------|\n");
130310
}
131311

132312
static void printLine(
133313
final PrintWriter out,
134314
final String cfName,
135315
final String keys,
136-
final String columnSize,
137-
final String sstFilesSize) {
138-
final String format = "| %-30s | %-15s | %-12s | %-15s |\n";
139-
out.format(format, cfName, keys, columnSize, sstFilesSize);
316+
final String totalFilesSize,
317+
final String sstFilesSize,
318+
final String blobFilesSize) {
319+
final String format = "| %-30s | %-15s | %-11s | %-15s | %-16s |\n";
320+
out.format(format, cfName, keys, totalFilesSize, sstFilesSize, blobFilesSize);
140321
}
322+
323+
record ColumnFamilyUsage(
324+
String name, long keys, long totalSize, long sstFilesSize, long blobFilesSize) {}
141325
}

besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.hyperledger.besu.cli.util.VersionProvider;
2020

2121
import java.io.PrintWriter;
22+
import java.util.ArrayList;
23+
import java.util.List;
2224

2325
import org.rocksdb.RocksDBException;
2426
import picocli.CommandLine;
@@ -31,12 +33,12 @@
3133
description = "Print RocksDB information",
3234
mixinStandardHelpOptions = true,
3335
versionProvider = VersionProvider.class,
34-
subcommands = {RocksDbSubCommand.RocksDbUsage.class})
36+
subcommands = {RocksDbSubCommand.RocksDbUsage.class, RocksDbSubCommand.RocksDbStats.class})
3537
public class RocksDbSubCommand implements Runnable {
3638

3739
@SuppressWarnings("unused")
3840
@ParentCommand
39-
private StorageSubCommand parentCommand;
41+
private StorageSubCommand storageSubCommand;
4042

4143
@SuppressWarnings("unused")
4244
@CommandLine.Spec
@@ -60,29 +62,74 @@ static class RocksDbUsage implements Runnable {
6062

6163
@SuppressWarnings("unused")
6264
@ParentCommand
63-
private RocksDbSubCommand parentCommand;
65+
private RocksDbSubCommand rocksDbSubCommand;
6466

6567
@Override
6668
public void run() {
6769

6870
final PrintWriter out = spec.commandLine().getOut();
6971

7072
final String dbPath =
71-
parentCommand
72-
.parentCommand
73-
.parentCommand
73+
rocksDbSubCommand
74+
.storageSubCommand
75+
.besuCommand
7476
.dataDir()
7577
.toString()
7678
.concat("/")
7779
.concat(DATABASE_PATH);
7880

7981
RocksDbHelper.printTableHeader(out);
8082

83+
final List<RocksDbHelper.ColumnFamilyUsage> columnFamilyUsages = new ArrayList<>();
8184
RocksDbHelper.forEachColumnFamily(
8285
dbPath,
8386
(rocksdb, cfHandle) -> {
8487
try {
85-
RocksDbHelper.printUsageForColumnFamily(rocksdb, cfHandle, out);
88+
columnFamilyUsages.add(
89+
RocksDbHelper.getAndPrintUsageForColumnFamily(rocksdb, cfHandle, out));
90+
} catch (RocksDBException e) {
91+
throw new RuntimeException(e);
92+
}
93+
});
94+
RocksDbHelper.printTotals(out, columnFamilyUsages);
95+
}
96+
}
97+
98+
@Command(
99+
name = "x-stats",
100+
description = "Print rocksdb stats",
101+
mixinStandardHelpOptions = true,
102+
versionProvider = VersionProvider.class)
103+
static class RocksDbStats implements Runnable {
104+
105+
@SuppressWarnings("unused")
106+
@CommandLine.Spec
107+
private CommandLine.Model.CommandSpec spec;
108+
109+
@SuppressWarnings("unused")
110+
@ParentCommand
111+
private RocksDbSubCommand rocksDbSubCommand;
112+
113+
@Override
114+
public void run() {
115+
116+
final PrintWriter out = spec.commandLine().getOut();
117+
118+
final String dbPath =
119+
rocksDbSubCommand
120+
.storageSubCommand
121+
.besuCommand
122+
.dataDir()
123+
.toString()
124+
.concat("/")
125+
.concat(DATABASE_PATH);
126+
127+
out.println("Column Family Stats...");
128+
RocksDbHelper.forEachColumnFamily(
129+
dbPath,
130+
(rocksdb, cfHandle) -> {
131+
try {
132+
RocksDbHelper.printStatsForColumnFamily(rocksdb, cfHandle, out);
86133
} catch (RocksDBException e) {
87134
throw new RuntimeException(e);
88135
}

besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public class StorageSubCommand implements Runnable {
5757

5858
@SuppressWarnings("unused")
5959
@ParentCommand
60-
BesuCommand parentCommand;
60+
BesuCommand besuCommand;
6161

6262
@SuppressWarnings("unused")
6363
@Spec
@@ -104,8 +104,8 @@ public void run() {
104104

105105
private StorageProvider getStorageProvider() {
106106
// init collection of ignorable segments
107-
parentCommand.parentCommand.setIgnorableStorageSegments();
108-
return parentCommand.parentCommand.getStorageProvider();
107+
parentCommand.besuCommand.setIgnorableStorageSegments();
108+
return parentCommand.besuCommand.getStorageProvider();
109109
}
110110

111111
private void revert(final StorageProvider storageProvider) {

0 commit comments

Comments
 (0)