diff --git a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java index 88e52a532..b2a50bfcc 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java @@ -26,6 +26,7 @@ public abstract class CompactOffHeapLinearHashTable { // to fit 64 bits per slot. public static final int MAX_TIER_CHUNKS = 1 << 30; public static final int MAX_TIER_ENTRIES = 1 << 29; + public static final double MAX_LOAD_FACTOR = .2/.3; public static int valueBits(long actualChunksPerSegment) { @@ -57,7 +58,7 @@ public abstract class CompactOffHeapLinearHashTable { if (entriesPerSegment < 0L) throw new IllegalArgumentException("entriesPerSegment should be positive"); long capacity = Maths.nextPower2(entriesPerSegment, 64L); - if (((double) entriesPerSegment) / (double) capacity > 2./3.) { + if (((double) entriesPerSegment) / (double) capacity > MAX_LOAD_FACTOR) { // hash lookup shouldn't be too dense capacity <<= 1L; } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index fdae95a00..0cd23670a 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -106,6 +106,7 @@ public abstract class VanillaChronicleHash "tierHashLookupKeyBits").int32(); tierHashLookupEntrySize = wireIn.read(() -> "tierHashLookupEntrySize").int32(); tierHashLookupCapacity = wireIn.read(() -> "tierHashLookupCapacity").int64(); + maxEntriesPerHashLookup = wireIn.read(() -> "maxEntriesPerHashLookup").int64(); tierHashLookupInnerSize = wireIn.read(() -> "tierHashLookupInnerSize").int64(); tierHashLookupOuterSize = wireIn.read(() -> "tierHashLookupOuterSize").int64(); @@ -300,6 +303,7 @@ public abstract class VanillaChronicleHash "tierHashLookupKeyBits").int32(tierHashLookupKeyBits); wireOut.write(() -> "tierHashLookupEntrySize").int32(tierHashLookupEntrySize); wireOut.write(() -> "tierHashLookupCapacity").int64(tierHashLookupCapacity); + wireOut.write(() -> "maxEntriesPerHashLookup").int64(maxEntriesPerHashLookup); wireOut.write(() -> "tierHashLookupInnerSize").int64(tierHashLookupInnerSize); wireOut.write(() -> "tierHashLookupOuterSize").int64(tierHashLookupOuterSize); diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java index a19cf91fc..42acc754c 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java @@ -635,7 +635,9 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { " chucks, " + h.maxChunksPerEntry + " is maximum."); } long lowestPossiblyFreeChunk = lowestPossiblyFreeChunk(); - if (lowestPossiblyFreeChunk == h.actualChunksPerSegmentTier) + if (lowestPossiblyFreeChunk + chunks > h.actualChunksPerSegmentTier) + return -1; + if (tierEntries() >= h.maxEntriesPerHashLookup) return -1; assert lowestPossiblyFreeChunk < h.actualChunksPerSegmentTier; long ret = freeList.setNextNContinuousClearBits(lowestPossiblyFreeChunk, chunks);