Skip to content

Commit dc80d4a

Browse files
committed
Added MerkleDbConfig.goodAverageBucketEntryCount config to replace HDHM.GOOD_AVERAGE_BUCKET_ENTRY_COUNT
Signed-off-by: Artem Ananev <[email protected]>
1 parent 9670e26 commit dc80d4a

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/config/MerkleDbConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
* @param indexRebuildingEnforced
4747
* Configuration used to avoid reading stored indexes from a saved state and enforce rebuilding those indexes from
4848
* data files.
49+
* @param goodAverageBucketEntryCount
50+
* Target average number of entries in HalfDiskHashMap buckets. This number is used to calculate the number
51+
* of buckets to allocate based on projected virtual map size, and also to check if it's time to double the
52+
* number of HalfDiskHashMap buckets.
4953
* @param tablesToRepairHdhm
5054
* Comma-delimited list of data source names, may be empty. When a MerkleDb data source with a name from the
5155
* list is loaded from a snapshot, its key to path map will be rebuilt from path to KV data files. Note that
@@ -80,6 +84,7 @@ public record MerkleDbConfig(
8084
@Positive @ConfigProperty(defaultValue = "16777216") int iteratorInputBufferBytes,
8185
@ConfigProperty(defaultValue = "false") boolean reconnectKeyLeakMitigationEnabled,
8286
@ConfigProperty(defaultValue = "false") boolean indexRebuildingEnforced,
87+
@ConfigProperty(defaultValue = "32") int goodAverageBucketEntryCount,
8388
@ConfigProperty(defaultValue = "") String tablesToRepairHdhm,
8489
@ConfigProperty(defaultValue = "75.0") double percentHalfDiskHashMapFlushThreads,
8590
@ConfigProperty(defaultValue = "-1") int numHalfDiskHashMapFlushThreads,

platform-sdk/swirlds-merkledb/src/main/java/com/swirlds/merkledb/files/hashmap/HalfDiskHashMap.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public class HalfDiskHashMap implements AutoCloseable, Snapshotable, FileStatist
7575
* starts to exceed the number of buckets times this average number of entries, the
7676
* map is resized by doubling the number of buckets.
7777
*/
78-
private static final long GOOD_AVERAGE_BUCKET_ENTRY_COUNT = 32;
78+
private final int goodAverageBucketEntryCount;
7979

8080
/** The limit on the number of concurrent read tasks in {@code endWriting()} */
8181
private static final int MAX_IN_FLIGHT = 1024;
@@ -208,10 +208,11 @@ public HalfDiskHashMap(
208208
throws IOException {
209209
this.config = requireNonNull(configuration);
210210
final MerkleDbConfig merkleDbConfig = this.config.getConfigData(MerkleDbConfig.class);
211+
this.goodAverageBucketEntryCount = merkleDbConfig.goodAverageBucketEntryCount();
211212
// Max number of keys is limited by merkleDbConfig.maxNumberOfKeys. Number of buckets is,
212213
// on average, GOOD_AVERAGE_BUCKET_ENTRY_COUNT times smaller than the number of keys. To
213214
// be on the safe side, double that amount and use as a hard limit for bucket index size
214-
final long bucketIndexCapacity = merkleDbConfig.maxNumOfKeys() * 2 / GOOD_AVERAGE_BUCKET_ENTRY_COUNT;
215+
final long bucketIndexCapacity = merkleDbConfig.maxNumOfKeys() * 2 / goodAverageBucketEntryCount;
215216
this.storeName = storeName;
216217
Path indexFile = storeDir.resolve(storeName + BUCKET_INDEX_FILENAME_SUFFIX);
217218
// create bucket pool
@@ -274,7 +275,7 @@ public HalfDiskHashMap(
274275
// create store dir
275276
Files.createDirectories(storeDir);
276277
// calculate number of entries we can store in a disk page
277-
final int minimumBuckets = (int) (initialCapacity / GOOD_AVERAGE_BUCKET_ENTRY_COUNT);
278+
final int minimumBuckets = (int) (initialCapacity / goodAverageBucketEntryCount);
278279
// numOfBuckets is the nearest power of two greater than minimumBuckets with a min of 2
279280
setNumberOfBuckets(Math.max(Integer.highestOneBit(minimumBuckets) * 2, 2));
280281
// create new index
@@ -886,15 +887,15 @@ private Bucket readBucket(final int bucketIndex) throws IOException {
886887

887888
/**
888889
* Check if this map should be resized, given the new virtual map size. If the new map size
889-
* exceeds 80% of the current number of buckets times {@link #GOOD_AVERAGE_BUCKET_ENTRY_COUNT},
890+
* exceeds 80% of the current number of buckets times {@link #goodAverageBucketEntryCount},
890891
* the map is resized by doubling the number of buckets.
891892
*
892893
* @param firstLeafPath The first leaf virtual path
893894
* @param lastLeafPath The last leaf virtual path
894895
*/
895896
public void resizeIfNeeded(final long firstLeafPath, final long lastLeafPath) {
896897
final long currentSize = lastLeafPath - firstLeafPath + 1;
897-
if (currentSize / numOfBuckets.get() <= GOOD_AVERAGE_BUCKET_ENTRY_COUNT * 80 / 100) {
898+
if (currentSize / numOfBuckets.get() <= goodAverageBucketEntryCount * 80 / 100) {
898899
// No need to resize yet
899900
return;
900901
}
@@ -928,10 +929,10 @@ public void printStats() {
928929
"""
929930
HalfDiskHashMap Stats {
930931
numOfBuckets = {}
931-
GOOD_AVERAGE_BUCKET_ENTRY_COUNT = {}
932+
goodAverageBucketEntryCount = {}
932933
}""",
933934
numOfBuckets,
934-
GOOD_AVERAGE_BUCKET_ENTRY_COUNT);
935+
goodAverageBucketEntryCount);
935936
}
936937

937938
public DataFileCollection getFileCollection() {
@@ -954,6 +955,11 @@ private void setNumberOfBuckets(final int newValue) {
954955
bucketMaskBits.set(trailingZeroes);
955956
}
956957

958+
// For testing purposes
959+
int getNumOfBuckets() {
960+
return numOfBuckets.get();
961+
}
962+
957963
/**
958964
* Computes which bucket a key with the given hash falls. Depends on the fact the numOfBuckets
959965
* is a power of two. Based on same calculation that is used in java HashMap.

0 commit comments

Comments
 (0)