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