Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
8250984: Memory Docker tests fail on some Linux kernels w/o cgroupv1 …
…swap limit capabilities

Reviewed-by: yan
Backport-of: 0187567
  • Loading branch information
Ekaterina Vergizova authored and Yuri Nesterenko committed Dec 4, 2020
1 parent e22699c commit a48eb78
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 43 deletions.
Expand Up @@ -225,6 +225,8 @@ private static void setSubSystemPath(Metrics metric, String[] entry) {
MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
boolean isHierarchial = getHierarchical(memorySubSystem);
memorySubSystem.setHierarchical(isHierarchial);
boolean isSwapEnabled = getSwapEnabled(memorySubSystem);
memorySubSystem.setSwapEnabled(isSwapEnabled);
}
metric.setActiveSubSystems();
}
Expand All @@ -234,6 +236,12 @@ private static void setSubSystemPath(Metrics metric, String[] entry) {
}


private static boolean getSwapEnabled(MemorySubSystem subsystem) {
long retval = SubSystem.getLongValue(subsystem, "memory.memsw.limit_in_bytes");
return retval > 0;
}


private static boolean getHierarchical(MemorySubSystem subsystem) {
long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
return hierarchical > 0;
Expand Down Expand Up @@ -468,10 +476,16 @@ public long getTcpMemoryUsage() {
}

public long getMemoryAndSwapFailCount() {
if (!memory.isSwapEnabled()) {
return getMemoryFailCount();
}
return SubSystem.getLongValue(memory, "memory.memsw.failcnt");
}

public long getMemoryAndSwapLimit() {
if (!memory.isSwapEnabled()) {
return getMemoryLimit();
}
long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
if (retval > unlimited_minimum) {
if (memory.isHierarchical()) {
Expand All @@ -488,10 +502,16 @@ public long getMemoryAndSwapLimit() {
}

public long getMemoryAndSwapMaxUsage() {
if (!memory.isSwapEnabled()) {
return getMemoryMaxUsage();
}
return SubSystem.getLongValue(memory, "memory.memsw.max_usage_in_bytes");
}

public long getMemoryAndSwapUsage() {
if (!memory.isSwapEnabled()) {
return getMemoryUsage();
}
return SubSystem.getLongValue(memory, "memory.memsw.usage_in_bytes");
}

Expand Down
Expand Up @@ -266,6 +266,7 @@ public static int[] StringRangeToIntArray(String range) {
public static class MemorySubSystem extends SubSystem {

private boolean hierarchical;
private boolean swapenabled;

public MemorySubSystem(String root, String mountPoint) {
super(root, mountPoint);
Expand All @@ -279,5 +280,12 @@ void setHierarchical(boolean hierarchical) {
this.hierarchical = hierarchical;
}

boolean isSwapEnabled() {
return swapenabled;
}

void setSwapEnabled(boolean swapenabled) {
this.swapenabled = swapenabled;
}
}
}
18 changes: 13 additions & 5 deletions test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java
Expand Up @@ -148,14 +148,22 @@ private static void testOperatingSystemMXBeanAwareness(String memoryAllocation,
out.shouldHaveExitValue(0)
.shouldContain("Checking OperatingSystemMXBean")
.shouldContain("OperatingSystemMXBean.getTotalPhysicalMemorySize: " + expectedMemory)
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [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 does not return the expected result, but 0
.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.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: 0");
out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [0-9]+");
}

try {
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");
} catch(RuntimeException ex) {
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");
}
}

Expand Down
46 changes: 28 additions & 18 deletions test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java
Expand Up @@ -61,26 +61,34 @@ private static void testMemoryLimit(String value) {
}

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][];
for (int i = 0; i < 64; i++) {
try {
bytes[i] = new byte[8 * 1024 * 1024];
// 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][];
for (int i = 0; i < 64; i++) {
try {
bytes[i] = new byte[8 * 1024 * 1024];
// 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 (Metrics.systemMetrics().getMemoryFailCount() <= count) {
throw new RuntimeException("Memory fail count : new : ["
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
+ ", old : [" + count + "]");
if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
throw new RuntimeException("Memory fail count : new : ["
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
+ ", old : [" + count + "]");
}
}
System.out.println("TEST PASSED!!!");
}
Expand Down Expand Up @@ -112,10 +120,12 @@ private static void testKernelMemoryLimit(String value) {
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() + "]");
Expand Down
43 changes: 23 additions & 20 deletions test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java
Expand Up @@ -310,29 +310,32 @@ public void testMemorySubsystem() {
}

// Memory and Swap
oldVal = metrics.getMemoryAndSwapFailCount();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
}
// Skip swap tests if no swap is configured.
if (metrics.getMemoryAndSwapLimit() > metrics.getMemoryLimit()) {
oldVal = metrics.getMemoryAndSwapFailCount();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
}

oldVal = metrics.getMemoryAndSwapLimit();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes");
newVal = newVal > unlimited_minimum ? -1L : newVal;
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
}
oldVal = metrics.getMemoryAndSwapLimit();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes");
newVal = newVal > unlimited_minimum ? -1L : newVal;
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
}

oldVal = metrics.getMemoryAndSwapMaxUsage();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
}
oldVal = metrics.getMemoryAndSwapMaxUsage();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
}

oldVal = metrics.getMemoryAndSwapUsage();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
oldVal = metrics.getMemoryAndSwapUsage();
newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes");
if (!compareWithErrorMargin(oldVal, newVal)) {
fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
}
}

oldVal = metrics.getMemorySoftLimit();
Expand Down

1 comment on commit a48eb78

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.