From adfec1b61352af03ad3fbb2a2651ca0428d1771b Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 17 Oct 2014 09:12:25 +0100 Subject: [PATCH] Give more conservative head room for avoid Map's with an imperfect hash distribution filling up. --- .../net/openhft/chronicle/map/ChronicleMapBuilder.java | 7 ++++++- .../map/serialization/CopyingMetaBytesInterop.java | 8 ++++---- .../java/net/openhft/chronicle/map/OSResizesMain.java | 9 ++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index a5e8cf385..71c83fe3f 100644 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -385,8 +385,13 @@ public class ChronicleMapBuilder implements Cloneable, if (actualEntriesPerSegment > 0) return actualEntriesPerSegment; int as = actualSegments(); + long actualEntries = + as == 1 ? entries + 1 : // The extra 1 might not be needed. + as <= 4 ? entries * 10L / 9 : // 10%, assumes you are trying to be tight. + entries * 5L / 4; // 25% + // round up to the next multiple of 64. - return (int) (Math.max(1, entries * 2L / as) + 63) & ~63; + return (int) (Math.max(1, actualEntries / as) + 63) & ~63; } @Override diff --git a/src/main/java/net/openhft/chronicle/map/serialization/CopyingMetaBytesInterop.java b/src/main/java/net/openhft/chronicle/map/serialization/CopyingMetaBytesInterop.java index a8fc3d368..79e6111e3 100644 --- a/src/main/java/net/openhft/chronicle/map/serialization/CopyingMetaBytesInterop.java +++ b/src/main/java/net/openhft/chronicle/map/serialization/CopyingMetaBytesInterop.java @@ -16,14 +16,14 @@ package net.openhft.chronicle.map.serialization; +import net.openhft.chronicle.map.threadlocal.Provider; +import net.openhft.chronicle.map.threadlocal.StatefulCopyable; +import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies; import net.openhft.lang.io.Bytes; import net.openhft.lang.io.DirectBytes; import net.openhft.lang.io.DirectStore; import net.openhft.lang.io.serialization.BytesMarshaller; import net.openhft.lang.io.serialization.JDKObjectSerializer; -import net.openhft.chronicle.map.threadlocal.Provider; -import net.openhft.chronicle.map.threadlocal.StatefulCopyable; -import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies; import java.io.IOException; import java.io.ObjectInputStream; @@ -190,7 +190,7 @@ public abstract class CopyingMetaBytesInterop implements MetaBytesInterop< forBytesWriter = new ForBytesWriter(); } - private Bytes obtain(long maxSize) { + Bytes obtain(long maxSize) { DirectBytes buf; if ((buf = buffer) != null) { if (maxSize <= buf.capacity()) { diff --git a/src/test/java/net/openhft/chronicle/map/OSResizesMain.java b/src/test/java/net/openhft/chronicle/map/OSResizesMain.java index 3792462b5..34f8907a7 100644 --- a/src/test/java/net/openhft/chronicle/map/OSResizesMain.java +++ b/src/test/java/net/openhft/chronicle/map/OSResizesMain.java @@ -34,9 +34,8 @@ public class OSResizesMain { public static void main(String[] args) throws IOException, InterruptedException { File file = File.createTempFile("over-sized", "deleteme"); ChronicleMap map = ChronicleMapBuilder.of(String.class, String.class) - - .entrySize(1024 * 1024) - .entries(1024 * 1024) + .entrySize(100 * 1024 * 1024) + .entries(1000000) .create(file); for (int i = 0; i < 10000; i++) { char[] chars = new char[i]; @@ -48,6 +47,10 @@ public class OSResizesMain { file.length() / 1e9, run("du", "-h", file.getAbsolutePath()).split("\\s")[0], run("grep", "over-sized", "/proc/" + Jvm.getProcessId() + "/maps").split("\\s")[0]); + // show up in top. + long time = System.currentTimeMillis(); + while (time + 20000 > System.currentTimeMillis()) + Thread.yield(); map.close(); file.delete(); }