Skip to content

Commit 07138e4

Browse files
authored
history-expiry: RocksDB BlobDB GC tuning CLI Config (#8599)
- --Xplugin-rocksdb-blob-garbage-collection-age-cutoff configures blob_garbage_collection_age_cutoff - --Xplugin-rocksdb-blob-garbage-collection-force-threshold configures blob_garbage_collection_force_threshold - --Xplugin-rocksdb-blockchain-blob-garbage-collection-enabled to configure BLOCKCHAIN BlobDB GC specifically - Unspecified GC settings should default to RocksDB defaults (rather than hardcoding RocksDB defaults in Besu) - Display BlobDB GC settings in config overview --------- Signed-off-by: Simon Dudley <[email protected]>
1 parent 00a18e2 commit 07138e4

File tree

14 files changed

+363
-41
lines changed

14 files changed

+363
-41
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
### Upcoming Breaking Changes
88
### Additions and Improvements
9+
- `--Xplugin-rocksdb-blockchain-blob-garbage-collection-enabled` Adds ability to enabled BlobDB GC for BLOCKCHAIN column family [#8599](https://github.com/hyperledger/besu/pull/8599)
10+
- `--Xplugin-rocksdb-blob-garbage-collection-age-cutoff`, `--Xplugin-rocksdb-blob-garbage-collection-force-threshold` BlobDB GC config options [#8599](https://github.com/hyperledger/besu/pull/8599)
911

1012
## 25.5.0
1113
### Breaking Changes

besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,18 +2817,19 @@ private String generateConfigurationOverview() {
28172817
final PathBasedExtraStorageConfiguration subStorageConfiguration =
28182818
getDataStorageConfiguration().getPathBasedExtraStorageConfiguration();
28192819
if (subStorageConfiguration.getLimitTrieLogsEnabled()) {
2820-
builder.setLimitTrieLogsEnabled();
2821-
builder.setTrieLogRetentionLimit(subStorageConfiguration.getMaxLayersToLoad());
2822-
builder.setTrieLogsPruningWindowSize(subStorageConfiguration.getTrieLogPruningWindowSize());
2820+
builder
2821+
.setLimitTrieLogsEnabled()
2822+
.setTrieLogRetentionLimit(subStorageConfiguration.getMaxLayersToLoad())
2823+
.setTrieLogsPruningWindowSize(subStorageConfiguration.getTrieLogPruningWindowSize());
28232824
}
28242825
}
28252826

2826-
builder.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled());
2827-
2828-
builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation());
2829-
builder.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode());
2830-
2831-
builder.setPluginContext(this.besuPluginContext);
2827+
builder
2828+
.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled())
2829+
.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation())
2830+
.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode())
2831+
.setPluginContext(this.besuPluginContext)
2832+
.setBlobDBSettings(rocksDBPlugin.getBlobDBSettings());
28322833

28332834
return builder.build();
28342835
}

besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
1818
import org.hyperledger.besu.evm.internal.EvmConfiguration;
19+
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions;
1920
import org.hyperledger.besu.services.BesuPluginContextImpl;
2021
import org.hyperledger.besu.util.BesuVersionUtils;
2122
import org.hyperledger.besu.util.log.FramedLogMessage;
@@ -61,6 +62,7 @@ public class ConfigurationOverviewBuilder {
6162
private EvmConfiguration.WorldUpdaterMode worldStateUpdateMode;
6263
private Map<String, String> environment;
6364
private BesuPluginContextImpl besuPluginContext;
65+
private RocksDBCLIOptions.BlobDBSettings blobDBSettings;
6466

6567
/**
6668
* Create a new ConfigurationOverviewBuilder.
@@ -302,6 +304,30 @@ public ConfigurationOverviewBuilder setEnvironment(final Map<String, String> env
302304
return this;
303305
}
304306

307+
/**
308+
* set the plugin context
309+
*
310+
* @param besuPluginContext the plugin context
311+
* @return the builder
312+
*/
313+
public ConfigurationOverviewBuilder setPluginContext(
314+
final BesuPluginContextImpl besuPluginContext) {
315+
this.besuPluginContext = besuPluginContext;
316+
return this;
317+
}
318+
319+
/**
320+
* Sets the blob db settings.
321+
*
322+
* @param blobDBSettings the blob db settings
323+
* @return the builder
324+
*/
325+
public ConfigurationOverviewBuilder setBlobDBSettings(
326+
final RocksDBCLIOptions.BlobDBSettings blobDBSettings) {
327+
this.blobDBSettings = blobDBSettings;
328+
return this;
329+
}
330+
305331
/**
306332
* Build configuration overview.
307333
*
@@ -364,16 +390,8 @@ public String build() {
364390

365391
lines.add("Using " + txPoolImplementation + " transaction pool implementation");
366392

367-
if (isHighSpec) {
368-
lines.add("Experimental high spec configuration enabled");
369-
}
370-
371393
lines.add("Using " + worldStateUpdateMode + " worldstate update mode");
372394

373-
if (isSnapServerEnabled) {
374-
lines.add("Experimental Snap Sync server enabled");
375-
}
376-
377395
if (isLimitTrieLogsEnabled) {
378396
final StringBuilder trieLogPruningString = new StringBuilder();
379397
trieLogPruningString
@@ -385,6 +403,34 @@ public String build() {
385403
lines.add(trieLogPruningString.toString());
386404
}
387405

406+
if (isSnapServerEnabled) {
407+
lines.add("Experimental Snap Sync server enabled");
408+
}
409+
410+
if (isHighSpec) {
411+
lines.add("Experimental high spec configuration enabled");
412+
}
413+
414+
if (blobDBSettings != null && blobDBSettings.isBlockchainGarbageCollectionEnabled()) {
415+
lines.add("Experimental BlobDB BLOCKCHAIN Garbage Collection enabled");
416+
}
417+
if (hasCustomBlobDBSettings()) {
418+
final StringBuilder blobDBString = new StringBuilder();
419+
blobDBString.append("Experimental BlobDB GC ");
420+
if (blobDBSettings.blobGarbageCollectionAgeCutoff().isPresent()) {
421+
blobDBString
422+
.append("age cutoff: ")
423+
.append(blobDBSettings.blobGarbageCollectionAgeCutoff().get())
424+
.append("; ");
425+
}
426+
if (blobDBSettings.blobGarbageCollectionForceThreshold().isPresent()) {
427+
blobDBString
428+
.append("force threshold: ")
429+
.append(blobDBSettings.blobGarbageCollectionForceThreshold().get());
430+
}
431+
lines.add(blobDBString.toString());
432+
}
433+
388434
lines.add("");
389435
lines.add("Host:");
390436

@@ -415,6 +461,12 @@ public String build() {
415461
return FramedLogMessage.generate(lines);
416462
}
417463

464+
private boolean hasCustomBlobDBSettings() {
465+
return blobDBSettings != null
466+
&& (blobDBSettings.blobGarbageCollectionAgeCutoff().isPresent()
467+
|| blobDBSettings.blobGarbageCollectionForceThreshold().isPresent());
468+
}
469+
418470
private void detectJemalloc(final List<String> lines) {
419471
Optional.ofNullable(Objects.isNull(environment) ? null : environment.get("BESU_USING_JEMALLOC"))
420472
.ifPresentOrElse(
@@ -447,13 +499,4 @@ private void detectJemalloc(final List<String> lines) {
447499
private String normalizeSize(final long size) {
448500
return String.format("%.02f", (double) (size) / 1024 / 1024 / 1024) + " GB";
449501
}
450-
451-
/**
452-
* set the plugin context
453-
*
454-
* @param besuPluginContext the plugin context
455-
*/
456-
public void setPluginContext(final BesuPluginContextImpl besuPluginContext) {
457-
this.besuPluginContext = besuPluginContext;
458-
}
459502
}

besu/src/test/java/org/hyperledger/besu/RunnerTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,10 @@ private StorageProvider createKeyValueStorageProvider(
424424
DEFAULT_MAX_OPEN_FILES,
425425
DEFAULT_BACKGROUND_THREAD_COUNT,
426426
DEFAULT_CACHE_CAPACITY,
427-
DEFAULT_IS_HIGH_SPEC),
427+
DEFAULT_IS_HIGH_SPEC,
428+
false,
429+
Optional.empty(),
430+
Optional.empty()),
428431
Arrays.asList(KeyValueSegmentIdentifier.values()),
429432
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS))
430433
.withCommonConfiguration(besuConfiguration)

besu/src/test/java/org/hyperledger/besu/components/PrivacyTestModule.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.nio.file.Files;
3535
import java.nio.file.Path;
3636
import java.util.Arrays;
37+
import java.util.Optional;
3738
import javax.inject.Named;
3839
import javax.inject.Singleton;
3940

@@ -101,7 +102,10 @@ PrivacyStorageProvider provideKeyValueStorageProvider(
101102
DEFAULT_MAX_OPEN_FILES,
102103
DEFAULT_BACKGROUND_THREAD_COUNT,
103104
DEFAULT_CACHE_CAPACITY,
104-
DEFAULT_IS_HIGH_SPEC),
105+
DEFAULT_IS_HIGH_SPEC,
106+
false,
107+
Optional.empty(),
108+
Optional.empty()),
105109
Arrays.asList(KeyValueSegmentIdentifier.values()),
106110
RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS)))
107111
.withCommonConfiguration(besuConfiguration)

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsai/AbstractIsolationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ protected StorageProvider createKeyValueStorageProvider() {
202202
1024 /* MAX_OPEN_FILES*/,
203203
4 /*BACKGROUND_THREAD_COUNT*/,
204204
8388608 /*CACHE_CAPACITY*/,
205-
false),
205+
false,
206+
false,
207+
Optional.empty(),
208+
Optional.empty()),
206209
Arrays.asList(KeyValueSegmentIdentifier.values()),
207210
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS))
208211
.withCommonConfiguration(

ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ private StorageProvider createKeyValueStorageProvider(final Path dataDir, final
178178
DEFAULT_MAX_OPEN_FILES,
179179
DEFAULT_BACKGROUND_THREAD_COUNT,
180180
DEFAULT_CACHE_CAPACITY,
181-
DEFAULT_IS_HIGH_SPEC),
181+
DEFAULT_IS_HIGH_SPEC,
182+
false,
183+
Optional.empty(),
184+
Optional.empty()),
182185
Arrays.asList(KeyValueSegmentIdentifier.values()),
183186
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS))
184187
.withCommonConfiguration(besuConfiguration)

plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBPlugin.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ public boolean isHighSpecEnabled() {
117117
return options.isHighSpec();
118118
}
119119

120+
/**
121+
* Gets blob db settings.
122+
*
123+
* @return the blob db settings
124+
*/
125+
public RocksDBCLIOptions.BlobDBSettings getBlobDBSettings() {
126+
return options.getBlobDBSettings();
127+
}
128+
120129
private void createAndRegister(final StorageService service) {
121130
final List<SegmentIdentifier> segments = service.getAllSegmentIdentifiers();
122131

plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/configuration/RocksDBCLIOptions.java

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
package org.hyperledger.besu.plugin.services.storage.rocksdb.configuration;
1616

17+
import java.util.Optional;
18+
1719
import com.google.common.base.MoreObjects;
1820
import picocli.CommandLine;
1921

@@ -45,6 +47,18 @@ public class RocksDBCLIOptions {
4547
/** The constant IS_HIGH_SPEC. */
4648
public static final String IS_HIGH_SPEC = "--Xplugin-rocksdb-high-spec-enabled";
4749

50+
/** Key name for configuring blockchain_blob_garbage_collection_enabled */
51+
public static final String BLOB_BLOCKCHAIN_GARBAGE_COLLECTION_ENABLED =
52+
"--Xplugin-rocksdb-blockchain-blob-garbage-collection-enabled";
53+
54+
/** Key name for configuring blob_garbage_collection_age_cutoff */
55+
public static final String BLOB_GARBAGE_COLLECTION_AGE_CUTOFF =
56+
"--Xplugin-rocksdb-blob-garbage-collection-age-cutoff";
57+
58+
/** Key name for configuring blob_garbage_collection_force_threshold */
59+
public static final String BLOB_GARBAGE_COLLECTION_FORCE_THRESHOLD =
60+
"--Xplugin-rocksdb-blob-garbage-collection-force-threshold";
61+
4862
/** The Max open files. */
4963
@CommandLine.Option(
5064
names = {MAX_OPEN_FILES_FLAG},
@@ -81,6 +95,39 @@ public class RocksDBCLIOptions {
8195
"Use this flag to boost Besu performance if you have a 16 GiB RAM hardware or more (default: ${DEFAULT-VALUE})")
8296
boolean isHighSpec;
8397

98+
/** The Blob blockchain garbage collection enabled. */
99+
@CommandLine.Option(
100+
names = {BLOB_BLOCKCHAIN_GARBAGE_COLLECTION_ENABLED},
101+
hidden = true,
102+
paramLabel = "<BOOLEAN>",
103+
description =
104+
"Enable garbage collection for the BLOCKCHAIN column family (default: ${DEFAULT-VALUE})")
105+
boolean isBlockchainGarbageCollectionEnabled = false;
106+
107+
/**
108+
* The Blob garbage collection age cutoff. The fraction of file age to be considered eligible for
109+
* GC; e.g. 0.25 = oldest 25% of files eligible; e.g. 1 = all files eligible When unspecified, use
110+
* RocksDB default
111+
*/
112+
@CommandLine.Option(
113+
names = {BLOB_GARBAGE_COLLECTION_AGE_CUTOFF},
114+
hidden = true,
115+
paramLabel = "<DOUBLE>",
116+
description = "Blob garbage collection age cutoff (default: ${DEFAULT-VALUE})")
117+
Optional<Double> blobGarbageCollectionAgeCutoff = Optional.empty();
118+
119+
/**
120+
* The Blob garbage collection force threshold. The fraction of garbage inside eligible blob files
121+
* to trigger GC; e.g. 1 = trigger when eligible file contains 100% garbage; e.g. 0 = trigger for
122+
* all eligible files; When unspecified, use Rocksdb default
123+
*/
124+
@CommandLine.Option(
125+
names = {BLOB_GARBAGE_COLLECTION_FORCE_THRESHOLD},
126+
hidden = true,
127+
paramLabel = "<DOUBLE>",
128+
description = "Blob garbage collection force threshold (default: ${DEFAULT-VALUE})")
129+
Optional<Double> blobGarbageCollectionForceThreshold = Optional.empty();
130+
84131
private RocksDBCLIOptions() {}
85132

86133
/**
@@ -104,6 +151,9 @@ public static RocksDBCLIOptions fromConfig(final RocksDBConfiguration config) {
104151
options.cacheCapacity = config.getCacheCapacity();
105152
options.backgroundThreadCount = config.getBackgroundThreadCount();
106153
options.isHighSpec = config.isHighSpec();
154+
options.isBlockchainGarbageCollectionEnabled = config.isBlockchainGarbageCollectionEnabled();
155+
options.blobGarbageCollectionAgeCutoff = config.getBlobGarbageCollectionAgeCutoff();
156+
options.blobGarbageCollectionForceThreshold = config.getBlobGarbageCollectionForceThreshold();
107157
return options;
108158
}
109159

@@ -114,7 +164,13 @@ public static RocksDBCLIOptions fromConfig(final RocksDBConfiguration config) {
114164
*/
115165
public RocksDBFactoryConfiguration toDomainObject() {
116166
return new RocksDBFactoryConfiguration(
117-
maxOpenFiles, backgroundThreadCount, cacheCapacity, isHighSpec);
167+
maxOpenFiles,
168+
backgroundThreadCount,
169+
cacheCapacity,
170+
isHighSpec,
171+
isBlockchainGarbageCollectionEnabled,
172+
blobGarbageCollectionAgeCutoff,
173+
blobGarbageCollectionForceThreshold);
118174
}
119175

120176
/**
@@ -126,13 +182,40 @@ public boolean isHighSpec() {
126182
return isHighSpec;
127183
}
128184

185+
/**
186+
* Gets blob db settings.
187+
*
188+
* @return the blob db settings
189+
*/
190+
public BlobDBSettings getBlobDBSettings() {
191+
return new BlobDBSettings(
192+
isBlockchainGarbageCollectionEnabled,
193+
blobGarbageCollectionAgeCutoff,
194+
blobGarbageCollectionForceThreshold);
195+
}
196+
129197
@Override
130198
public String toString() {
131199
return MoreObjects.toStringHelper(this)
132200
.add("maxOpenFiles", maxOpenFiles)
133201
.add("cacheCapacity", cacheCapacity)
134202
.add("backgroundThreadCount", backgroundThreadCount)
135203
.add("isHighSpec", isHighSpec)
204+
.add("isBlockchainGarbageCollectionEnabled", isBlockchainGarbageCollectionEnabled)
205+
.add("blobGarbageCollectionAgeCutoff", blobGarbageCollectionAgeCutoff)
206+
.add("blobGarbageCollectionForceThreshold", blobGarbageCollectionForceThreshold)
136207
.toString();
137208
}
209+
210+
/**
211+
* A container type BlobDBSettings
212+
*
213+
* @param isBlockchainGarbageCollectionEnabled the is blockchain garbage collection enabled
214+
* @param blobGarbageCollectionAgeCutoff the blob garbage collection age cutoff
215+
* @param blobGarbageCollectionForceThreshold the blob garbage collection force threshold
216+
*/
217+
public record BlobDBSettings(
218+
boolean isBlockchainGarbageCollectionEnabled,
219+
Optional<Double> blobGarbageCollectionAgeCutoff,
220+
Optional<Double> blobGarbageCollectionForceThreshold) {}
138221
}

0 commit comments

Comments
 (0)