From c10cb3d3a96e4e83b6ad0b497576f95769480c00 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 31 Jan 2024 19:54:08 +1000 Subject: [PATCH] Store trielog as blobdb (#6289) Store trielog as blobdb to improve performance. * Store trie_log_storage as blob * changelog * Add gc flag for static data * Updating plugin-api build.gradle with new hash as SegmentIdentifier interface has introduced new method Signed-off-by: Usman Saleem --- CHANGELOG.md | 1 + .../keyvalue/KeyValueSegmentIdentifier.java | 24 ++++++++++++------- plugin-api/build.gradle | 2 +- .../services/storage/SegmentIdentifier.java | 10 ++++++++ .../RocksDBColumnarKeyValueStorage.java | 2 +- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a650aa6d0..b1681d5c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Introduce `besu storage x-trie-log prune` experimental offline subcommand which will prune all redundant trie logs except the latest 512 [#6303](https://github.com/hyperledger/besu/pull/6303) - Introduce caching mechanism to optimize Keccak hash calculations for account storage slots during block processing [#6452](https://github.com/hyperledger/besu/pull/6452) - Added configuration options for `pragueTime` to genesis file for Prague fork development [#6473](https://github.com/hyperledger/besu/pull/6473) +- Moving trielog storage to RocksDB's blobdb to improve write amplications [#6289](https://github.com/hyperledger/besu/pull/6289) ### Bug fixes - 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) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java index 282c314157..9326c97b32 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java @@ -23,15 +23,15 @@ import org.bouncycastle.util.Arrays; public enum KeyValueSegmentIdentifier implements SegmentIdentifier { DEFAULT("default".getBytes(StandardCharsets.UTF_8)), BLOCKCHAIN(new byte[] {1}, true, true), - WORLD_STATE(new byte[] {2}, new int[] {0, 1}, false, true), + WORLD_STATE(new byte[] {2}, new int[] {0, 1}, false, true, false), PRIVATE_TRANSACTIONS(new byte[] {3}), PRIVATE_STATE(new byte[] {4}), PRUNING_STATE(new byte[] {5}, new int[] {0, 1}), - ACCOUNT_INFO_STATE(new byte[] {6}, new int[] {2}, false, true), + ACCOUNT_INFO_STATE(new byte[] {6}, new int[] {2}, false, true, false), CODE_STORAGE(new byte[] {7}, new int[] {2}), - ACCOUNT_STORAGE_STORAGE(new byte[] {8}, new int[] {2}, false, true), - TRIE_BRANCH_STORAGE(new byte[] {9}, new int[] {2}, false, true), - TRIE_LOG_STORAGE(new byte[] {10}, new int[] {2}), + ACCOUNT_STORAGE_STORAGE(new byte[] {8}, new int[] {2}, false, true, false), + TRIE_BRANCH_STORAGE(new byte[] {9}, new int[] {2}, false, true, false), + TRIE_LOG_STORAGE(new byte[] {10}, new int[] {2}, true, false, true), VARIABLES(new byte[] {11}), // formerly GOQUORUM_PRIVATE_WORLD_STATE // previously supported GoQuorum private states @@ -49,6 +49,7 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier { private final int[] versionList; private final boolean containsStaticData; private final boolean eligibleToHighSpecFlag; + private final boolean staticDataGarbageCollectionEnabled; KeyValueSegmentIdentifier(final byte[] id) { this(id, new int[] {0, 1, 2}); @@ -56,22 +57,24 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier { KeyValueSegmentIdentifier( final byte[] id, final boolean containsStaticData, final boolean eligibleToHighSpecFlag) { - this(id, new int[] {0, 1, 2}, containsStaticData, eligibleToHighSpecFlag); + this(id, new int[] {0, 1, 2}, containsStaticData, eligibleToHighSpecFlag, false); } KeyValueSegmentIdentifier(final byte[] id, final int[] versionList) { - this(id, versionList, false, false); + this(id, versionList, false, false, false); } KeyValueSegmentIdentifier( final byte[] id, final int[] versionList, final boolean containsStaticData, - final boolean eligibleToHighSpecFlag) { + final boolean eligibleToHighSpecFlag, + final boolean staticDataGarbageCollectionEnabled) { this.id = id; this.versionList = versionList; this.containsStaticData = containsStaticData; this.eligibleToHighSpecFlag = eligibleToHighSpecFlag; + this.staticDataGarbageCollectionEnabled = staticDataGarbageCollectionEnabled; } @Override @@ -94,6 +97,11 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier { return eligibleToHighSpecFlag; } + @Override + public boolean isStaticDataGarbageCollectionEnabled() { + return staticDataGarbageCollectionEnabled; + } + @Override public boolean includeInDatabaseVersion(final int version) { return Arrays.contains(versionList, version); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 01ed8833da..ade07493c0 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'VpNy2KuAtEUc9hPguNivbjwy2YM3vIF444RCREJojqY=' + knownHash = '3+WNtdl1idY70N/MwVBbopU2ZWyWiu12YV1qaYXprZ8=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java index 5db7fea509..6633594370 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java @@ -64,4 +64,14 @@ public interface SegmentIdentifier { * @return true if the segment is involved with the high spec flag */ boolean isEligibleToHighSpecFlag(); + + /** + * Enable garbage collection for static data. This should be enabled for static data which can be + * deleted or pruned. + * + * @return true if enabled, false otherwise. + */ + default boolean isStaticDataGarbageCollectionEnabled() { + return false; + } } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index a7192cc3b5..5db32b4bc9 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -188,7 +188,7 @@ public abstract class RocksDBColumnarKeyValueStorage implements SegmentedKeyValu if (segment.containsStaticData()) { options .setEnableBlobFiles(true) - .setEnableBlobGarbageCollection(false) + .setEnableBlobGarbageCollection(segment.isStaticDataGarbageCollectionEnabled()) .setMinBlobSize(100) .setBlobCompressionType(CompressionType.LZ4_COMPRESSION); }