From 0cc07a6a9135908224e3e99eea11e77a5772a667 Mon Sep 17 00:00:00 2001 From: leventov Date: Wed, 17 Dec 2014 20:16:35 +0700 Subject: [PATCH] HCOLL-143 print a warning on attempt of creation too large ChronicleMap or ChronicleSet on Windows --- .../chronicle/map/ChronicleMapBuilder.java | 4 ++- .../chronicle/map/VanillaChronicleMap.java | 31 +++++++++++++++++++ .../chronicle/map/WarnOnWindowsTest.java | 30 ++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/test/java/net/openhft/chronicle/map/WarnOnWindowsTest.java diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index 04b9b53e7..9c62c7314 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -1172,6 +1172,7 @@ public final class ChronicleMapBuilder implements Cloneable, try { pushingToMapEventListener(); VanillaChronicleMap map = newMap(singleHashReplication, channel); + map.warnOnWindows(); BytesStore bytesStore = new DirectStore(JDKObjectSerializer.INSTANCE, map.sizeInBytes(), true); map.createMappedStoreAndSegments(bytesStore); @@ -1209,7 +1210,8 @@ public final class ChronicleMapBuilder implements Cloneable, } private VanillaChronicleMap newMap( - SingleChronicleHashReplication singleHashReplication, ReplicationChannel channel) throws IOException { + SingleChronicleHashReplication singleHashReplication, ReplicationChannel channel) + throws IOException { boolean replicated = singleHashReplication != null || channel != null; preMapConstruction(replicated); if (replicated) { diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index c8c54a67b..deae98e0c 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -32,6 +32,7 @@ import net.openhft.chronicle.hash.serialization.BytesInterop; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizeMarshaller; import net.openhft.chronicle.hash.serialization.internal.*; +import net.openhft.lang.Jvm; import net.openhft.lang.collection.DirectBitSet; import net.openhft.lang.collection.SingleThreadedDirectBitSet; import net.openhft.lang.io.*; @@ -237,7 +238,37 @@ class VanillaChronicleMap, return offset; } + void warnOnWindows() { + if (!Jvm.isWindows()) + return; + long offHeapMapSize = sizeInBytes(); + long oneGb = GIGABYTES.toBytes(1L); + double offHeapMapSizeInGb = offHeapMapSize * 1.0 / oneGb; + if (offHeapMapSize > GIGABYTES.toBytes(4L)) { + System.out.printf( + "WARNING: On Windows, you probably cannot create a ChronicleMap\n" + + "of more than 4 GB. The configured map requires %.2f GB of off-heap memory.\n", + offHeapMapSizeInGb); + } + try { + long freePhysicalMemory = Jvm.freePhysicalMemoryOnWindowsInBytes(); + if (offHeapMapSize > freePhysicalMemory * 0.9) { + double freePhysicalMemoryInGb = freePhysicalMemory * 1.0 / oneGb; + System.out.printf( + "WARNING: On Windows, you probably cannot create a ChronicleMap\n" + + "of more than 90%% of available free memory in the system.\n" + + "The configured map requires %.2f GB of off-heap memory.\n" + + "There is only %.2f GB of free physical memory in the system.\n", + offHeapMapSizeInGb, freePhysicalMemoryInGb); + + } + } catch (IOException e) { + // ignore -- anyway we just warn the user + } + } + final long createMappedStoreAndSegments(File file) throws IOException { + warnOnWindows(); return createMappedStoreAndSegments(new MappedStore(file, FileChannel.MapMode.READ_WRITE, sizeInBytes(), JDKObjectSerializer.INSTANCE)); } diff --git a/src/test/java/net/openhft/chronicle/map/WarnOnWindowsTest.java b/src/test/java/net/openhft/chronicle/map/WarnOnWindowsTest.java new file mode 100644 index 000000000..c3c0e36bc --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/WarnOnWindowsTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map; + +import org.junit.Ignore; +import org.junit.Test; + +public class WarnOnWindowsTest { + + @Test + @Ignore("This test results to OOM/jvm crash, run manually to verify warning output") + public void warnOnWindowsTest() { + ChronicleMapBuilder.of(Long.class, Long.class) + .entries(1_000_000_000).create(); + } +}