Add heap size bootstrap check
This commit adds a bootstrap check to ensure that the initial heap size and max heap size are set equal to each other.
This commit is contained in:
parent
5ca4304b23
commit
4f5d73bcb7
|
@ -26,6 +26,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.transport.BoundTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.discovery.zen.elect.ElectMasterService;
|
||||
import org.elasticsearch.monitor.jvm.JvmInfo;
|
||||
import org.elasticsearch.monitor.process.ProcessProbe;
|
||||
import org.elasticsearch.node.Node;
|
||||
|
||||
|
@ -108,6 +109,7 @@ final class BootstrapCheck {
|
|||
// the list of checks to execute
|
||||
static List<Check> checks(final Settings settings) {
|
||||
final List<Check> checks = new ArrayList<>();
|
||||
checks.add(new HeapSizeCheck());
|
||||
final FileDescriptorCheck fileDescriptorCheck
|
||||
= Constants.MAC_OS_X ? new OsXFileDescriptorCheck() : new FileDescriptorCheck();
|
||||
checks.add(fileDescriptorCheck);
|
||||
|
@ -143,6 +145,38 @@ final class BootstrapCheck {
|
|||
|
||||
}
|
||||
|
||||
static class HeapSizeCheck implements BootstrapCheck.Check {
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
final long initialHeapSize = getInitialHeapSize();
|
||||
final long maxHeapSize = getMaxHeapSize();
|
||||
return initialHeapSize != 0 && maxHeapSize != 0 && initialHeapSize != maxHeapSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String errorMessage() {
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
"initial heap size [%d] not equal to maximum heap size [%d]; " +
|
||||
"this can cause resize pauses and prevents mlockall from locking the entire heap",
|
||||
getInitialHeapSize(),
|
||||
getMaxHeapSize()
|
||||
);
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
long getInitialHeapSize() {
|
||||
return JvmInfo.jvmInfo().getConfiguredInitialHeapSize();
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
long getMaxHeapSize() {
|
||||
return JvmInfo.jvmInfo().getConfiguredMaxHeapSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class OsXFileDescriptorCheck extends FileDescriptorCheck {
|
||||
|
||||
public OsXFileDescriptorCheck() {
|
||||
|
|
|
@ -114,15 +114,33 @@ public class JvmInfo implements Streamable, ToXContent {
|
|||
Class<?> vmOptionClazz = Class.forName("com.sun.management.VMOption");
|
||||
PlatformManagedObject hotSpotDiagnosticMXBean = ManagementFactory.getPlatformMXBean(clazz);
|
||||
Method vmOptionMethod = clazz.getMethod("getVMOption", String.class);
|
||||
Object useCompressedOopsVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "UseCompressedOops");
|
||||
Method valueMethod = vmOptionClazz.getMethod("getValue");
|
||||
info.useCompressedOops = (String)valueMethod.invoke(useCompressedOopsVmOption);
|
||||
Object useG1GCVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "UseG1GC");
|
||||
info.useG1GC = (String)valueMethod.invoke(useG1GCVmOption);
|
||||
} catch (Throwable t) {
|
||||
// unable to deduce the state of compressed oops
|
||||
info.useCompressedOops = "unknown";
|
||||
info.useG1GC = "unknown";
|
||||
|
||||
try {
|
||||
Object useCompressedOopsVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "UseCompressedOops");
|
||||
info.useCompressedOops = (String) valueMethod.invoke(useCompressedOopsVmOption);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
Object useG1GCVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "UseG1GC");
|
||||
info.useG1GC = (String) valueMethod.invoke(useG1GCVmOption);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
Object initialHeapSizeVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "InitialHeapSize");
|
||||
info.configuredInitialHeapSize = Long.parseLong((String) valueMethod.invoke(initialHeapSizeVmOption));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
Object maxHeapSizeVmOption = vmOptionMethod.invoke(hotSpotDiagnosticMXBean, "MaxHeapSize");
|
||||
info.configuredMaxHeapSize = Long.parseLong((String) valueMethod.invoke(maxHeapSizeVmOption));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
|
||||
INSTANCE = info;
|
||||
|
@ -146,6 +164,9 @@ public class JvmInfo implements Streamable, ToXContent {
|
|||
|
||||
long startTime = -1;
|
||||
|
||||
private long configuredInitialHeapSize;
|
||||
private long configuredMaxHeapSize;
|
||||
|
||||
Mem mem;
|
||||
|
||||
String[] inputArguments;
|
||||
|
@ -159,9 +180,9 @@ public class JvmInfo implements Streamable, ToXContent {
|
|||
String[] gcCollectors = Strings.EMPTY_ARRAY;
|
||||
String[] memoryPools = Strings.EMPTY_ARRAY;
|
||||
|
||||
private String useCompressedOops;
|
||||
private String useCompressedOops = "unknown";
|
||||
|
||||
private String useG1GC;
|
||||
private String useG1GC = "unknown";
|
||||
|
||||
private JvmInfo() {
|
||||
}
|
||||
|
@ -286,6 +307,14 @@ public class JvmInfo implements Streamable, ToXContent {
|
|||
return this.systemProperties;
|
||||
}
|
||||
|
||||
public long getConfiguredInitialHeapSize() {
|
||||
return configuredInitialHeapSize;
|
||||
}
|
||||
|
||||
public long getConfiguredMaxHeapSize() {
|
||||
return configuredMaxHeapSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the JVM flag UseCompressedOops, if available otherwise
|
||||
* "unknown". The value "unknown" indicates that an attempt was
|
||||
|
|
|
@ -137,6 +137,49 @@ public class BootstrapCheckTests extends ESTestCase {
|
|||
assertThat(suppressed[1], hasToString(containsString("second")));
|
||||
}
|
||||
|
||||
public void testHeapSizeCheck() {
|
||||
final int initial = randomIntBetween(0, Integer.MAX_VALUE - 1);
|
||||
final int max = randomIntBetween(initial + 1, Integer.MAX_VALUE);
|
||||
final AtomicLong initialHeapSize = new AtomicLong(initial);
|
||||
final AtomicLong maxHeapSize = new AtomicLong(max);
|
||||
|
||||
final BootstrapCheck.HeapSizeCheck check = new BootstrapCheck.HeapSizeCheck() {
|
||||
@Override
|
||||
long getInitialHeapSize() {
|
||||
return initialHeapSize.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
long getMaxHeapSize() {
|
||||
return maxHeapSize.get();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
BootstrapCheck.check(true, Collections.singletonList(check), "testHeapSizeCheck");
|
||||
fail("should have failed to initial heap size not equal to max heap size");
|
||||
} catch (final RuntimeException e) {
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
containsString("initial heap size [" + initialHeapSize.get() + "] " +
|
||||
"not equal to maximum heap size [" + maxHeapSize.get() + "]")
|
||||
);
|
||||
}
|
||||
|
||||
initialHeapSize.set(maxHeapSize.get());
|
||||
|
||||
BootstrapCheck.check(true, Collections.singletonList(check), "testHeapSizeCheck");
|
||||
|
||||
// nothing should happen if the initial heap size or the max
|
||||
// heap size is not available
|
||||
if (randomBoolean()) {
|
||||
initialHeapSize.set(0);
|
||||
} else {
|
||||
maxHeapSize.set(0);
|
||||
}
|
||||
BootstrapCheck.check(true, Collections.singletonList(check), "testHeapSizeCheck");
|
||||
}
|
||||
|
||||
public void testFileDescriptorLimits() {
|
||||
final boolean osX = randomBoolean(); // simulates OS X versus non-OS X
|
||||
final int limit = osX ? 10240 : 1 << 16;
|
||||
|
|
Loading…
Reference in New Issue