HCOLL-408 Trigger new segment tier allocation on hashLookup overflow

This commit is contained in:
leventov
2015-12-07 12:31:28 +03:00
parent ce45903af7
commit c8483dfb7c
3 changed files with 9 additions and 2 deletions
@@ -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;
}
@@ -106,6 +106,7 @@ public abstract class VanillaChronicleHash<K,
public int tierHashLookupKeyBits;
public int tierHashLookupEntrySize;
public long tierHashLookupCapacity;
public long maxEntriesPerHashLookup;
long tierHashLookupInnerSize;
public long tierHashLookupOuterSize;
@@ -194,6 +195,7 @@ public abstract class VanillaChronicleHash<K,
"but hash lookup slot is " + tierHashLookupEntrySize);
}
tierHashLookupCapacity = CompactOffHeapLinearHashTable.capacityFor(entriesPerSegment);
maxEntriesPerHashLookup = (long) (tierHashLookupCapacity * MAX_LOAD_FACTOR);
tierHashLookupInnerSize = tierHashLookupCapacity * tierHashLookupEntrySize;
tierHashLookupOuterSize = CACHE_LINES.align(tierHashLookupInnerSize, BYTES);
@@ -255,6 +257,7 @@ public abstract class VanillaChronicleHash<K,
tierHashLookupKeyBits = wireIn.read(() -> "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<K,
wireOut.write(() -> "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);
@@ -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);