Blobdb for static data (#5475)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/5542/head
Fabio Di Fabio 1 year ago committed by GitHub
parent 8bc939d236
commit 9ae1b535a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java
  3. 2
      plugin-api/build.gradle
  4. 9
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java
  5. 29
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java
  6. 15
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java

@ -12,6 +12,7 @@ and in case a rollback is needed, before installing a previous version, the migr
- Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) - Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466)
- Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) - Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529)
- remove PoW validation if merge is enabled as it is not needed anymore [#5538](https://github.com/hyperledger/besu/pull/5538) - remove PoW validation if merge is enabled as it is not needed anymore [#5538](https://github.com/hyperledger/besu/pull/5538)
- Use BlobDB for blockchain storage to reduce initial sync time and write amplification [#5475](https://github.com/hyperledger/besu/pull/5475)
### Bug Fixes ### Bug Fixes
- check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) - check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527)

@ -19,7 +19,7 @@ import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Arrays;
public enum KeyValueSegmentIdentifier implements SegmentIdentifier { public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
BLOCKCHAIN(new byte[] {1}), BLOCKCHAIN(new byte[] {1}, true),
WORLD_STATE(new byte[] {2}, new int[] {0, 1}), WORLD_STATE(new byte[] {2}, new int[] {0, 1}),
PRIVATE_TRANSACTIONS(new byte[] {3}), PRIVATE_TRANSACTIONS(new byte[] {3}),
PRIVATE_STATE(new byte[] {4}), PRIVATE_STATE(new byte[] {4}),
@ -44,14 +44,25 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
private final byte[] id; private final byte[] id;
private final int[] versionList; private final int[] versionList;
private final boolean containsStaticData;
KeyValueSegmentIdentifier(final byte[] id) { KeyValueSegmentIdentifier(final byte[] id) {
this(id, new int[] {0, 1, 2}); this(id, new int[] {0, 1, 2});
} }
KeyValueSegmentIdentifier(final byte[] id, final boolean containsStaticData) {
this(id, new int[] {0, 1, 2}, containsStaticData);
}
KeyValueSegmentIdentifier(final byte[] id, final int[] versionList) { KeyValueSegmentIdentifier(final byte[] id, final int[] versionList) {
this(id, versionList, false);
}
KeyValueSegmentIdentifier(
final byte[] id, final int[] versionList, final boolean containsStaticData) {
this.id = id; this.id = id;
this.versionList = versionList; this.versionList = versionList;
this.containsStaticData = containsStaticData;
} }
@Override @Override
@ -64,6 +75,11 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
return id; return id;
} }
@Override
public boolean containsStaticData() {
return containsStaticData;
}
@Override @Override
public boolean includeInDatabaseVersion(final int version) { public boolean includeInDatabaseVersion(final int version) {
return Arrays.contains(versionList, version); return Arrays.contains(versionList, version);

@ -69,7 +69,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) { tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought" description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files files = sourceSets.main.allJava.files
knownHash = 'V3sh575rrexPv+Ywe8mURT4Z3fREDCDd79PpAISFx8A=' knownHash = '5qYaRONxsvjtA3/9OOX4B1GEaOVEXLyU2zBFU0Kpu0E='
} }
check.dependsOn('checkAPIChanges') check.dependsOn('checkAPIChanges')

@ -47,4 +47,13 @@ public interface SegmentIdentifier {
default boolean includeInDatabaseVersion(final int version) { default boolean includeInDatabaseVersion(final int version) {
return true; return true;
} }
/**
* Define if this segment contains data that is never updated, but only added and optionally
* deleted. Example is append only data like the blockchain. This information can be used by the
* underlying implementation to apply specific optimization for this use case.
*
* @return true if the segment contains only static data
*/
boolean containsStaticData();
} }

@ -153,16 +153,7 @@ public abstract class RocksDBColumnarKeyValueStorage
.noneMatch(existed -> Arrays.equals(existed, ignorableSegment.getId()))) .noneMatch(existed -> Arrays.equals(existed, ignorableSegment.getId())))
.forEach(trimmedSegments::remove); .forEach(trimmedSegments::remove);
columnDescriptors = columnDescriptors =
trimmedSegments.stream() trimmedSegments.stream().map(this::createColumnDescriptor).collect(Collectors.toList());
.map(
segment ->
new ColumnFamilyDescriptor(
segment.getId(),
new ColumnFamilyOptions()
.setTtl(0)
.setCompressionType(CompressionType.LZ4_COMPRESSION)
.setTableFormatConfig(createBlockBasedTableConfig(configuration))))
.collect(Collectors.toList());
columnDescriptors.add( columnDescriptors.add(
new ColumnFamilyDescriptor( new ColumnFamilyDescriptor(
DEFAULT_COLUMN.getBytes(StandardCharsets.UTF_8), DEFAULT_COLUMN.getBytes(StandardCharsets.UTF_8),
@ -180,6 +171,24 @@ public abstract class RocksDBColumnarKeyValueStorage
} }
} }
private ColumnFamilyDescriptor createColumnDescriptor(final SegmentIdentifier segment) {
final var options =
new ColumnFamilyOptions()
.setTtl(0)
.setCompressionType(CompressionType.LZ4_COMPRESSION)
.setTableFormatConfig(createBlockBasedTableConfig(configuration));
if (segment.containsStaticData()) {
options
.setEnableBlobFiles(true)
.setEnableBlobGarbageCollection(false)
.setMinBlobSize(100)
.setBlobCompressionType(CompressionType.LZ4_COMPRESSION);
}
return new ColumnFamilyDescriptor(segment.getId(), options);
}
private void setGlobalOptions(final RocksDBConfiguration configuration, final Statistics stats) { private void setGlobalOptions(final RocksDBConfiguration configuration, final Statistics stats) {
options = new DBOptions(); options = new DBOptions();
options options

@ -261,14 +261,22 @@ public abstract class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValu
public enum TestSegment implements SegmentIdentifier { public enum TestSegment implements SegmentIdentifier {
FOO(new byte[] {1}), FOO(new byte[] {1}),
BAR(new byte[] {2}), BAR(new byte[] {2}),
EXPERIMENTAL(new byte[] {3}); EXPERIMENTAL(new byte[] {3}),
STATIC_DATA(new byte[] {4}, true);
private final byte[] id; private final byte[] id;
private final String nameAsUtf8; private final String nameAsUtf8;
private final boolean containsStaticData;
TestSegment(final byte[] id) { TestSegment(final byte[] id) {
this(id, false);
}
TestSegment(final byte[] id, final boolean containsStaticData) {
this.id = id; this.id = id;
this.nameAsUtf8 = new String(id, StandardCharsets.UTF_8); this.nameAsUtf8 = new String(id, StandardCharsets.UTF_8);
this.containsStaticData = containsStaticData;
} }
@Override @Override
@ -280,6 +288,11 @@ public abstract class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValu
public byte[] getId() { public byte[] getId() {
return id; return id;
} }
@Override
public boolean containsStaticData() {
return containsStaticData;
}
} }
protected abstract SegmentedKeyValueStorage<RocksDbSegmentIdentifier> createSegmentedStore() protected abstract SegmentedKeyValueStorage<RocksDbSegmentIdentifier> createSegmentedStore()

Loading…
Cancel
Save