Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,33 @@ static boolean tuneG1GCForSmallHeap(final long heapSize) {
}

static boolean tuneG1GCHeapRegion(final Map<String, JvmOption> finalJvmOptions, final boolean tuneG1GCForSmallHeap) {
JvmOption g1GCHeapRegion = finalJvmOptions.get("G1HeapRegionSize");
JvmOption g1GC = finalJvmOptions.get("UseG1GC");
return (tuneG1GCForSmallHeap && g1GC.getMandatoryValue().equals("true") && g1GCHeapRegion.isCommandLineOrigin() == false);
return tuneG1GCForSmallHeap && usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "G1HeapRegionSize");
}

static int tuneG1GCReservePercent(final Map<String, JvmOption> finalJvmOptions, final boolean tuneG1GCForSmallHeap) {
JvmOption g1GC = finalJvmOptions.get("UseG1GC");
JvmOption g1GCReservePercent = finalJvmOptions.get("G1ReservePercent");
if (g1GC.getMandatoryValue().equals("true")) {
if (g1GCReservePercent.isCommandLineOrigin() == false && tuneG1GCForSmallHeap) {
return 15;
} else if (g1GCReservePercent.isCommandLineOrigin() == false && tuneG1GCForSmallHeap == false) {
return 25;
}
if (usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "G1ReservePercent")) {
return tuneG1GCForSmallHeap ? 15 : 25;
}
return 0;
}

static boolean tuneG1GCInitiatingHeapOccupancyPercent(final Map<String, JvmOption> finalJvmOptions) {
JvmOption g1GC = finalJvmOptions.get("UseG1GC");
JvmOption g1GCInitiatingHeapOccupancyPercent = finalJvmOptions.get("InitiatingHeapOccupancyPercent");
return g1GCInitiatingHeapOccupancyPercent.isCommandLineOrigin() == false && g1GC.getMandatoryValue().equals("true");
return usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "InitiatingHeapOccupancyPercent");
}

private static boolean usingG1GcWithoutCommandLineOriginOption(Map<String, JvmOption> finalJvmOptions, String optionName) {
return getRequiredOption(finalJvmOptions, "UseG1GC").getMandatoryValue().equals("true")
&& getRequiredOption(finalJvmOptions, optionName).isCommandLineOrigin() == false;
}

private static JvmOption getRequiredOption(final Map<String, JvmOption> finalJvmOptions, final String key) {
final var jvmOption = finalJvmOptions.get(key);
if (jvmOption == null) {
throw new IllegalStateException(
"JVM option [" + key + "] was unexpectedly missing. Elasticsearch requires this option to be present."
);
}
return jvmOption;
}

private static final Pattern SYSTEM_PROPERTY = Pattern.compile("^-D(?<key>[\\w+].*?)=(?<value>.*)$");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

package org.elasticsearch.server.cli;

import org.elasticsearch.common.Strings;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -29,6 +31,11 @@ class JvmOption {
private final String origin;

JvmOption(String value, String origin) {
if (origin == null) {
throw new IllegalStateException(Strings.format("""
Elasticsearch could not determine the origin of JVM option [%s]. \
This indicates that it is running in an unsupported configuration.""", value));
}
this.value = value;
this.origin = origin;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.everyItem;
Expand Down Expand Up @@ -179,4 +180,46 @@ public void testMaxDirectMemorySizeChoiceWhenSet() throws Exception {
);
}

@SuppressWarnings("ConstantConditions")
public void testMissingOptionHandling() {
final Map<String, JvmOption> g1GcOn = Map.of("UseG1GC", new JvmOption("true", ""));
final Map<String, JvmOption> g1GcOff = Map.of("UseG1GC", new JvmOption("", ""));

assertFalse(JvmErgonomics.tuneG1GCHeapRegion(Map.of(), false));
assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCHeapRegion(Map.of(), true)).getMessage(),
allOf(containsString("[UseG1GC]"), containsString("unexpectedly missing"))
);
assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCHeapRegion(g1GcOn, true)).getMessage(),
allOf(containsString("[G1HeapRegionSize]"), containsString("unexpectedly missing"))
);
assertFalse(JvmErgonomics.tuneG1GCHeapRegion(g1GcOff, randomBoolean()));

assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCReservePercent(Map.of(), randomBoolean())).getMessage(),
allOf(containsString("[UseG1GC]"), containsString("unexpectedly missing"))
);
assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCReservePercent(g1GcOn, randomBoolean())).getMessage(),
allOf(containsString("[G1ReservePercent]"), containsString("unexpectedly missing"))
);
assertEquals(0, JvmErgonomics.tuneG1GCReservePercent(g1GcOff, randomBoolean()));

assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCInitiatingHeapOccupancyPercent(Map.of())).getMessage(),
allOf(containsString("[UseG1GC]"), containsString("unexpectedly missing"))
);
assertThat(
expectThrows(IllegalStateException.class, () -> JvmErgonomics.tuneG1GCInitiatingHeapOccupancyPercent(g1GcOn)).getMessage(),
allOf(containsString("[InitiatingHeapOccupancyPercent]"), containsString("unexpectedly missing"))
);
assertFalse(JvmErgonomics.tuneG1GCInitiatingHeapOccupancyPercent(g1GcOff));

assertThat(
expectThrows(IllegalStateException.class, () -> new JvmOption("OptionName", null)).getMessage(),
allOf(containsString("could not determine the origin of JVM option [OptionName]"), containsString("unsupported"))
);
}

}