8250984: Memory Docker tests fail on some Linux kernels w/o cgroupv1 …
Reviewed-by: bobv, sgehwolf
This commit is contained in:
parent
a75edc29c6
commit
0187567704
@ -28,6 +28,7 @@ package jdk.internal.platform.cgroupv1;
|
||||
public class CgroupV1MemorySubSystemController extends CgroupV1SubsystemController {
|
||||
|
||||
private boolean hierarchical;
|
||||
private boolean swapenabled;
|
||||
|
||||
public CgroupV1MemorySubSystemController(String root, String mountPoint) {
|
||||
super(root, mountPoint);
|
||||
@ -41,4 +42,11 @@ public class CgroupV1MemorySubSystemController extends CgroupV1SubsystemControll
|
||||
this.hierarchical = hierarchical;
|
||||
}
|
||||
|
||||
}
|
||||
boolean isSwapEnabled() {
|
||||
return swapenabled;
|
||||
}
|
||||
|
||||
void setSwapEnabled(boolean swapenabled) {
|
||||
this.swapenabled = swapenabled;
|
||||
}
|
||||
}
|
||||
|
@ -199,6 +199,8 @@ public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics {
|
||||
CgroupV1MemorySubSystemController memorySubSystem = (CgroupV1MemorySubSystemController)controller;
|
||||
boolean isHierarchial = getHierarchical(memorySubSystem);
|
||||
memorySubSystem.setHierarchical(isHierarchial);
|
||||
boolean isSwapEnabled = getSwapEnabled(memorySubSystem);
|
||||
memorySubSystem.setSwapEnabled(isSwapEnabled);
|
||||
}
|
||||
subsystem.setActiveSubSystems();
|
||||
}
|
||||
@ -208,6 +210,12 @@ public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics {
|
||||
}
|
||||
|
||||
|
||||
private static boolean getSwapEnabled(CgroupV1MemorySubSystemController controller) {
|
||||
long retval = getLongValue(controller, "memory.memsw.limit_in_bytes");
|
||||
return retval > 0;
|
||||
}
|
||||
|
||||
|
||||
private static boolean getHierarchical(CgroupV1MemorySubSystemController controller) {
|
||||
long hierarchical = getLongValue(controller, "memory.use_hierarchy");
|
||||
return hierarchical > 0;
|
||||
@ -438,10 +446,16 @@ public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics {
|
||||
}
|
||||
|
||||
public long getMemoryAndSwapFailCount() {
|
||||
if (!memory.isSwapEnabled()) {
|
||||
return getMemoryFailCount();
|
||||
}
|
||||
return getLongValue(memory, "memory.memsw.failcnt");
|
||||
}
|
||||
|
||||
public long getMemoryAndSwapLimit() {
|
||||
if (!memory.isSwapEnabled()) {
|
||||
return getMemoryLimit();
|
||||
}
|
||||
long retval = getLongValue(memory, "memory.memsw.limit_in_bytes");
|
||||
if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) {
|
||||
if (memory.isHierarchical()) {
|
||||
@ -457,10 +471,16 @@ public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics {
|
||||
}
|
||||
|
||||
public long getMemoryAndSwapMaxUsage() {
|
||||
if (!memory.isSwapEnabled()) {
|
||||
return getMemoryMaxUsage();
|
||||
}
|
||||
return getLongValue(memory, "memory.memsw.max_usage_in_bytes");
|
||||
}
|
||||
|
||||
public long getMemoryAndSwapUsage() {
|
||||
if (!memory.isSwapEnabled()) {
|
||||
return getMemoryUsage();
|
||||
}
|
||||
return getLongValue(memory, "memory.memsw.usage_in_bytes");
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,6 @@ runtime/cds/DeterministicDump.java 8253495 generic-all
|
||||
runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java 8253081 generic-all
|
||||
runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64
|
||||
runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all
|
||||
containers/docker/TestMemoryAwareness.java 8250984 linux-5.4.0-1019-oracle
|
||||
|
||||
#############################################################################
|
||||
|
||||
|
@ -45,7 +45,7 @@ public class PlainRead {
|
||||
oa.shouldNotMatch("^.*" + what + " *" + value + ".*$");
|
||||
}
|
||||
|
||||
static final String good_value = "(\\d+|-1|Unlimited)";
|
||||
static final String good_value = "(\\d+|-1|-2|Unlimited)";
|
||||
static final String bad_value = "(failed)";
|
||||
|
||||
static final String[] variables = {"Memory Limit is:", "CPU Shares is:", "CPU Quota is:", "CPU Period is:", "active_processor_count:"};
|
||||
|
@ -153,18 +153,24 @@ public class TestMemoryAwareness {
|
||||
out.shouldHaveExitValue(0)
|
||||
.shouldContain("Checking OperatingSystemMXBean")
|
||||
.shouldContain("OperatingSystemMXBean.getTotalPhysicalMemorySize: " + expectedMemory)
|
||||
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+")
|
||||
.shouldContain("OperatingSystemMXBean.getTotalMemorySize: " + expectedMemory)
|
||||
.shouldMatch("OperatingSystemMXBean\\.getFreeMemorySize: [1-9][0-9]+")
|
||||
.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");
|
||||
// in case of warnings like : "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap."
|
||||
// the getTotalSwapSpaceSize returns the system values as the container setup isn't supported in that case.
|
||||
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+");
|
||||
|
||||
// in case of warnings like : "Your kernel does not support swap limit capabilities
|
||||
// or the cgroup is not mounted. Memory limited without swap."
|
||||
// the getTotalSwapSpaceSize and getFreeSwapSpaceSize return the system
|
||||
// values as the container setup isn't supported in that case.
|
||||
try {
|
||||
out.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: " + expectedSwap);
|
||||
} catch(RuntimeException ex) {
|
||||
out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [1-9][0-9]+");
|
||||
out.shouldContain("Metrics.getMemoryLimit() == " + expectedMemory);
|
||||
out.shouldContain("Metrics.getMemoryAndSwapLimit() == -1");
|
||||
out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [0-9]+");
|
||||
}
|
||||
|
||||
try {
|
||||
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");
|
||||
} catch(RuntimeException ex) {
|
||||
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -905,8 +905,6 @@ jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-
|
||||
|
||||
# jdk_internal
|
||||
|
||||
jdk/internal/platform/docker/TestDockerMemoryMetrics.java 8250984 linux-5.4.0-1019-oracle
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_jpackage
|
||||
|
@ -66,34 +66,42 @@ public class MetricsMemoryTester {
|
||||
}
|
||||
|
||||
private static void testMemoryFailCount() {
|
||||
long count = Metrics.systemMetrics().getMemoryFailCount();
|
||||
long memAndSwapLimit = Metrics.systemMetrics().getMemoryAndSwapLimit();
|
||||
long memLimit = Metrics.systemMetrics().getMemoryLimit();
|
||||
|
||||
// Allocate 512M of data
|
||||
byte[][] bytes = new byte[64][];
|
||||
boolean atLeastOneAllocationWorked = false;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
try {
|
||||
bytes[i] = new byte[8 * 1024 * 1024];
|
||||
atLeastOneAllocationWorked = true;
|
||||
// Break out as soon as we see an increase in failcount
|
||||
// to avoid getting killed by the OOM killer.
|
||||
if (Metrics.systemMetrics().getMemoryFailCount() > count) {
|
||||
// We need swap to execute this test or will SEGV
|
||||
if (memAndSwapLimit <= memLimit) {
|
||||
System.out.println("No swap memory limits, test case skipped");
|
||||
} else {
|
||||
long count = Metrics.systemMetrics().getMemoryFailCount();
|
||||
|
||||
// Allocate 512M of data
|
||||
byte[][] bytes = new byte[64][];
|
||||
boolean atLeastOneAllocationWorked = false;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
try {
|
||||
bytes[i] = new byte[8 * 1024 * 1024];
|
||||
atLeastOneAllocationWorked = true;
|
||||
// Break out as soon as we see an increase in failcount
|
||||
// to avoid getting killed by the OOM killer.
|
||||
if (Metrics.systemMetrics().getMemoryFailCount() > count) {
|
||||
break;
|
||||
}
|
||||
} catch (Error e) { // OOM error
|
||||
break;
|
||||
}
|
||||
} catch (Error e) { // OOM error
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!atLeastOneAllocationWorked) {
|
||||
System.out.println("Allocation failed immediately. Ignoring test!");
|
||||
return;
|
||||
}
|
||||
// Be sure bytes allocations don't get optimized out
|
||||
System.out.println("DEBUG: Bytes allocation length 1: " + bytes[0].length);
|
||||
if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
|
||||
throw new RuntimeException("Memory fail count : new : ["
|
||||
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
|
||||
+ ", old : [" + count + "]");
|
||||
if (!atLeastOneAllocationWorked) {
|
||||
System.out.println("Allocation failed immediately. Ignoring test!");
|
||||
return;
|
||||
}
|
||||
// Be sure bytes allocations don't get optimized out
|
||||
System.out.println("DEBUG: Bytes allocation length 1: " + bytes[0].length);
|
||||
if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
|
||||
throw new RuntimeException("Memory fail count : new : ["
|
||||
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
|
||||
+ ", old : [" + count + "]");
|
||||
}
|
||||
}
|
||||
System.out.println("TEST PASSED!!!");
|
||||
}
|
||||
@ -131,10 +139,12 @@ public class MetricsMemoryTester {
|
||||
private static void testMemoryAndSwapLimit(String memory, String memAndSwap) {
|
||||
long expectedMem = getMemoryValue(memory);
|
||||
long expectedMemAndSwap = getMemoryValue(memAndSwap);
|
||||
long actualMemAndSwap = Metrics.systemMetrics().getMemoryAndSwapLimit();
|
||||
|
||||
if (expectedMem != Metrics.systemMetrics().getMemoryLimit()
|
||||
|| expectedMemAndSwap != Metrics.systemMetrics().getMemoryAndSwapLimit()) {
|
||||
System.err.println("Memory and swap limit not equal, expected : ["
|
||||
|| (expectedMemAndSwap != actualMemAndSwap
|
||||
&& expectedMem != actualMemAndSwap)) {
|
||||
throw new RuntimeException("Memory and swap limit not equal, expected : ["
|
||||
+ expectedMem + ", " + expectedMemAndSwap + "]"
|
||||
+ ", got : [" + Metrics.systemMetrics().getMemoryLimit()
|
||||
+ ", " + Metrics.systemMetrics().getMemoryAndSwapLimit() + "]");
|
||||
|
@ -293,29 +293,33 @@ public class MetricsTesterCgroupV1 implements CgroupMetricsTester {
|
||||
}
|
||||
|
||||
// Memory and Swap
|
||||
oldVal = metrics.getMemoryAndSwapFailCount();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.failcnt");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
|
||||
}
|
||||
|
||||
oldVal = metrics.getMemoryAndSwapLimit();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.limit_in_bytes");
|
||||
newVal = newVal > unlimited_minimum ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : newVal;
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
|
||||
}
|
||||
// Skip swap tests if no swap is configured.
|
||||
if (metrics.getMemoryAndSwapLimit() > metrics.getMemoryLimit()) {
|
||||
oldVal = metrics.getMemoryAndSwapFailCount();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.failcnt");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
|
||||
}
|
||||
|
||||
oldVal = metrics.getMemoryAndSwapMaxUsage();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.max_usage_in_bytes");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
|
||||
}
|
||||
oldVal = metrics.getMemoryAndSwapLimit();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.limit_in_bytes");
|
||||
newVal = newVal > unlimited_minimum ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : newVal;
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
|
||||
}
|
||||
|
||||
oldVal = metrics.getMemoryAndSwapUsage();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.usage_in_bytes");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
|
||||
oldVal = metrics.getMemoryAndSwapMaxUsage();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.max_usage_in_bytes");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
|
||||
}
|
||||
|
||||
oldVal = metrics.getMemoryAndSwapUsage();
|
||||
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.usage_in_bytes");
|
||||
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
|
||||
fail(Controller.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
|
||||
}
|
||||
}
|
||||
|
||||
oldVal = metrics.getMemorySoftLimit();
|
||||
|
Loading…
x
Reference in New Issue
Block a user