Skip to content

Commit 6572935

Browse files
committed
Adjust initial and max memory usage of builder.
1 parent e03ab4a commit 6572935

File tree

2 files changed

+79
-57
lines changed

2 files changed

+79
-57
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.driver;
26+
27+
import java.lang.management.ManagementFactory;
28+
import java.nio.file.Files;
29+
import java.nio.file.Paths;
30+
import java.util.regex.Matcher;
31+
import java.util.regex.Pattern;
32+
33+
import com.oracle.svm.core.OS;
34+
35+
class MemoryUtil {
36+
private static final double MAX_RAM_MIN_PERCENTAGE = 50.0;
37+
private static final double MAX_RAM_MAX_PERCENTAGE = 80.0;
38+
private static final double MAX_RAM_HEADROOM_PERCENTAGE = 10.0;
39+
40+
private static final Pattern MEMINFO_AVAILABLE_REGEX = Pattern.compile("^MemAvailable:\\s+(\\d+) kB");
41+
42+
public static double determineMaxRAMPercentage() {
43+
double availableRAMPercentage = Math.floor(getAvailableRAMPercentage() - MAX_RAM_HEADROOM_PERCENTAGE);
44+
return Math.max(MAX_RAM_MIN_PERCENTAGE, Math.min(availableRAMPercentage, MAX_RAM_MAX_PERCENTAGE));
45+
}
46+
47+
private static double getAvailableRAMPercentage() {
48+
var osBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
49+
double usableMemory = osBean.getFreeMemorySize();
50+
// TODO: drop debug code
51+
System.out.println("Free memory percentage: " + (usableMemory / osBean.getTotalMemorySize()));
52+
if (OS.LINUX.isCurrent()) {
53+
// Increase value if more memory is available on Linux.
54+
usableMemory = Math.max(usableMemory, getLinuxAvailableMemory());
55+
// TODO: drop debug code
56+
System.out.println("Available memory percentage: " + (usableMemory / osBean.getTotalMemorySize()));
57+
}
58+
return (usableMemory / osBean.getTotalMemorySize()) * 100;
59+
}
60+
61+
private static long getLinuxAvailableMemory() {
62+
try {
63+
String memAvailableLine = Files.readAllLines(Paths.get("/proc/meminfo")).stream().filter(l -> l.startsWith("MemAvailable")).findFirst().orElse("");
64+
Matcher m = MEMINFO_AVAILABLE_REGEX.matcher(memAvailableLine);
65+
if (m.matches()) {
66+
return Long.parseLong(m.group(1)) * 1024 /* kB to B */;
67+
}
68+
} catch (Exception e) {
69+
}
70+
return -1;
71+
}
72+
}

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import java.io.IOException;
3030
import java.io.InputStream;
3131
import java.io.InputStreamReader;
32-
import java.lang.management.ManagementFactory;
33-
import java.lang.management.OperatingSystemMXBean;
3432
import java.lang.reflect.Method;
3533
import java.nio.charset.StandardCharsets;
3634
import java.nio.file.Files;
@@ -58,7 +56,6 @@
5856
import java.util.function.BiFunction;
5957
import java.util.function.Consumer;
6058
import java.util.function.Function;
61-
import java.util.function.Supplier;
6259
import java.util.jar.Attributes;
6360
import java.util.jar.JarFile;
6461
import java.util.jar.Manifest;
@@ -808,11 +805,12 @@ static void ensureDirectoryExists(Path dir) {
808805

809806
private void prepareImageBuildArgs() {
810807
addImageBuilderJavaArgs("-Xss10m");
811-
addImageBuilderJavaArgs(oXms + getXmsValue());
812-
String xmxVal = getXmxValue(1);
813-
if (!"0".equals(xmxVal)) {
814-
addImageBuilderJavaArgs(oXmx + xmxVal);
815-
}
808+
809+
/* Builder needs at least 2GB of memory. */
810+
addImageBuilderJavaArgs("-Xms2g");
811+
812+
/* Adjust max memory usage depending on availability. */
813+
addImageBuilderJavaArgs("-XX:MaxRAMPercentage=" + MemoryUtil.determineMaxRAMPercentage());
816814

817815
/* Let builder exit on first OutOfMemoryError. */
818816
addImageBuilderJavaArgs("-XX:+ExitOnOutOfMemoryError");
@@ -863,27 +861,6 @@ protected static boolean replaceArg(Collection<String> args, String argPrefix, S
863861
return elementsRemoved;
864862
}
865863

866-
private static <T> T consolidateArgs(Collection<String> args, String argPrefix,
867-
Function<String, T> fromSuffix, Function<T, String> toSuffix,
868-
Supplier<T> init, BiFunction<T, T, T> combiner) {
869-
T consolidatedValue = null;
870-
boolean needsConsolidate = false;
871-
for (String arg : args) {
872-
if (arg.startsWith(argPrefix)) {
873-
if (consolidatedValue == null) {
874-
consolidatedValue = init.get();
875-
} else {
876-
needsConsolidate = true;
877-
}
878-
consolidatedValue = combiner.apply(consolidatedValue, fromSuffix.apply(arg.substring(argPrefix.length())));
879-
}
880-
}
881-
if (consolidatedValue != null && needsConsolidate) {
882-
replaceArg(args, argPrefix, toSuffix.apply(consolidatedValue));
883-
}
884-
return consolidatedValue;
885-
}
886-
887864
private static LinkedHashSet<String> collectListArgs(Collection<String> args, String argPrefix, String delimiter) {
888865
LinkedHashSet<String> allEntries = new LinkedHashSet<>();
889866
for (String arg : args) {
@@ -1052,14 +1029,7 @@ private int completeImageBuild() {
10521029
}
10531030
}
10541031
}
1055-
/* Perform JavaArgs consolidation - take the maximum of -Xmx, minimum of -Xms */
1056-
Long xmxValue = consolidateArgs(imageBuilderJavaArgs, oXmx, SubstrateOptionsParser::parseLong, String::valueOf, () -> 0L, Math::max);
1057-
Long xmsValue = consolidateArgs(imageBuilderJavaArgs, oXms, SubstrateOptionsParser::parseLong, String::valueOf, () -> SubstrateOptionsParser.parseLong(getXmsValue()), Math::max);
1058-
if (xmxValue != null) {
1059-
if (Long.compareUnsigned(xmsValue, xmxValue) > 0) {
1060-
replaceArg(imageBuilderJavaArgs, oXms, Long.toUnsignedString(xmxValue));
1061-
}
1062-
}
1032+
10631033
addImageBuilderJavaArgs(customJavaArgs.toArray(new String[0]));
10641034

10651035
/* Perform option consolidation of imageBuilderArgs */
@@ -2088,26 +2058,6 @@ List<String> getNativeImageArgs() {
20882058
return Stream.concat(getDefaultNativeImageArgs().stream(), config.getBuildArgs().stream()).toList();
20892059
}
20902060

2091-
protected String getXmsValue() {
2092-
return "1g";
2093-
}
2094-
2095-
@SuppressWarnings("deprecation") // getTotalPhysicalMemorySize is deprecated after JDK 11
2096-
private static long getPhysicalMemorySize() {
2097-
OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
2098-
long totalPhysicalMemorySize = ((com.sun.management.OperatingSystemMXBean) osMXBean).getTotalPhysicalMemorySize();
2099-
return totalPhysicalMemorySize;
2100-
}
2101-
2102-
protected String getXmxValue(int maxInstances) {
2103-
Long memMax = Long.divideUnsigned(Long.divideUnsigned(getPhysicalMemorySize(), 10) * 8, maxInstances);
2104-
String maxXmx = "14g";
2105-
if (Long.compareUnsigned(memMax, SubstrateOptionsParser.parseLong(maxXmx)) >= 0) {
2106-
return maxXmx;
2107-
}
2108-
return Long.toUnsignedString(memMax);
2109-
}
2110-
21112061
private static boolean isDumbTerm() {
21122062
String term = System.getenv().getOrDefault("TERM", "");
21132063
return term.isEmpty() || term.equals("dumb") || term.equals("unknown");

0 commit comments

Comments
 (0)