Limit max direct memory size to half of heap size (#42006)

This commit adds an ergonomic choice ot the max direct memory size such
that if it is not set, we default it to half of the heap size.
This commit is contained in:
Jason Tedor 2019-05-09 10:10:27 -04:00
parent ea5019665a
commit 970a2254c3
No known key found for this signature in database
GPG Key ID: FA89F05560F16BC5
2 changed files with 56 additions and 9 deletions

View File

@ -64,6 +64,10 @@ final class JvmErgonomics {
ergonomicChoices.add("-Dio.netty.allocator.type=pooled"); ergonomicChoices.add("-Dio.netty.allocator.type=pooled");
} }
} }
final long maxDirectMemorySize = extractMaxDirectMemorySize(finalJvmOptions);
if (maxDirectMemorySize == 0) {
ergonomicChoices.add("-XX:MaxDirectMemorySize=" + heapSize / 2);
}
return ergonomicChoices; return ergonomicChoices;
} }
@ -122,6 +126,10 @@ final class JvmErgonomics {
return Long.parseLong(finalJvmOptions.get("MaxHeapSize").get()); return Long.parseLong(finalJvmOptions.get("MaxHeapSize").get());
} }
static long extractMaxDirectMemorySize(final Map<String, Optional<String>> finalJvmOptions) {
return Long.parseLong(finalJvmOptions.get("MaxDirectMemorySize").get());
}
private static final Pattern SYSTEM_PROPERTY = Pattern.compile("^-D(?<key>[\\w+].*?)=(?<value>.*)$"); private static final Pattern SYSTEM_PROPERTY = Pattern.compile("^-D(?<key>[\\w+].*?)=(?<value>.*)$");
// package private for testing // package private for testing

View File

@ -23,14 +23,17 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.hasToString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -88,6 +91,19 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
} }
} }
public void testMaxDirectMemorySizeUnset() throws InterruptedException, IOException {
assertThat(
JvmErgonomics.extractMaxDirectMemorySize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-Xmx1g"))),
equalTo(0L));
}
public void testMaxDirectMemorySizeSet() throws InterruptedException, IOException {
assertThat(
JvmErgonomics.extractMaxDirectMemorySize(JvmErgonomics.finalJvmOptions(
Arrays.asList("-Xmx1g", "-XX:MaxDirectMemorySize=512m"))),
equalTo(512L << 20));
}
public void testExtractSystemProperties() { public void testExtractSystemProperties() {
Map<String, String> expectedSystemProperties = new HashMap<>(); Map<String, String> expectedSystemProperties = new HashMap<>();
expectedSystemProperties.put("file.encoding", "UTF-8"); expectedSystemProperties.put("file.encoding", "UTF-8");
@ -104,16 +120,39 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
assertTrue(parsedSystemProperties.isEmpty()); assertTrue(parsedSystemProperties.isEmpty());
} }
public void testLittleMemoryErgonomicChoices() throws InterruptedException, IOException { public void testPooledMemoryChoiceOnSmallHeap() throws InterruptedException, IOException {
String smallHeap = randomFrom(Arrays.asList("64M", "512M", "1024M", "1G")); final String smallHeap = randomFrom(Arrays.asList("64M", "512M", "1024M", "1G"));
List<String> expectedChoices = Collections.singletonList("-Dio.netty.allocator.type=unpooled"); assertThat(
assertEquals(expectedChoices, JvmErgonomics.choose(Arrays.asList("-Xms" + smallHeap, "-Xmx" + smallHeap))); JvmErgonomics.choose(Arrays.asList("-Xms" + smallHeap, "-Xmx" + smallHeap)),
hasItem("-Dio.netty.allocator.type=unpooled"));
} }
public void testPlentyMemoryErgonomicChoices() throws InterruptedException, IOException { public void testPooledMemoryChoiceOnNotSmallHeap() throws InterruptedException, IOException {
String largeHeap = randomFrom(Arrays.asList("1025M", "2048M", "2G", "8G")); final String largeHeap = randomFrom(Arrays.asList("1025M", "2048M", "2G", "8G"));
List<String> expectedChoices = Collections.singletonList("-Dio.netty.allocator.type=pooled"); assertThat(
assertEquals(expectedChoices, JvmErgonomics.choose(Arrays.asList("-Xms" + largeHeap, "-Xmx" + largeHeap))); JvmErgonomics.choose(Arrays.asList("-Xms" + largeHeap, "-Xmx" + largeHeap)),
hasItem("-Dio.netty.allocator.type=pooled"));
}
public void testMaxDirectMemorySizeChoice() throws InterruptedException, IOException {
final Map<String, String> heapMaxDirectMemorySize = Map.of(
"64M", Long.toString((64L << 20) / 2),
"512M", Long.toString((512L << 20) / 2),
"1024M", Long.toString((1024L << 20) / 2),
"1G", Long.toString((1L << 30) / 2),
"2048M", Long.toString((2048L << 20) / 2),
"2G", Long.toString((2L << 30) / 2),
"8G", Long.toString((8L << 30) / 2));
final String heapSize = randomFrom(heapMaxDirectMemorySize.keySet().toArray(String[]::new));
assertThat(
JvmErgonomics.choose(Arrays.asList("-Xms" + heapSize, "-Xmx" + heapSize)),
hasItem("-XX:MaxDirectMemorySize=" + heapMaxDirectMemorySize.get(heapSize)));
}
public void testMaxDirectMemorySizeChoiceWhenSet() throws InterruptedException, IOException {
assertThat(
JvmErgonomics.choose(Arrays.asList("-Xms1g", "-Xmx1g", "-XX:MaxDirectMemorySize=1g")),
everyItem(not(startsWith("-XX:MaxDirectMemorySize="))));
} }
} }