mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8299858: [Metrics] Swap memory limit reported incorrectly when too large
Reviewed-by: stuefe
This commit is contained in:
parent
28545dcf2b
commit
64ddf9536f
3 changed files with 67 additions and 3 deletions
|
@ -122,9 +122,11 @@ public class CgroupMetrics implements Metrics {
|
||||||
@Override
|
@Override
|
||||||
public long getMemoryLimit() {
|
public long getMemoryLimit() {
|
||||||
long subsMem = subsystem.getMemoryLimit();
|
long subsMem = subsystem.getMemoryLimit();
|
||||||
|
long systemTotal = getTotalMemorySize0();
|
||||||
|
assert(systemTotal > 0);
|
||||||
// Catch the cgroup memory limit exceeding host physical memory.
|
// Catch the cgroup memory limit exceeding host physical memory.
|
||||||
// Treat this as unlimited.
|
// Treat this as unlimited.
|
||||||
if (subsMem >= getTotalMemorySize0()) {
|
if (subsMem >= systemTotal) {
|
||||||
return CgroupSubsystem.LONG_RETVAL_UNLIMITED;
|
return CgroupSubsystem.LONG_RETVAL_UNLIMITED;
|
||||||
}
|
}
|
||||||
return subsMem;
|
return subsMem;
|
||||||
|
@ -142,7 +144,15 @@ public class CgroupMetrics implements Metrics {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getMemoryAndSwapLimit() {
|
public long getMemoryAndSwapLimit() {
|
||||||
return subsystem.getMemoryAndSwapLimit();
|
long totalSystemMemSwap = getTotalMemorySize0() + getTotalSwapSize0();
|
||||||
|
assert(totalSystemMemSwap > 0);
|
||||||
|
// Catch the cgroup memory and swap limit exceeding host physical swap
|
||||||
|
// and memory. Treat this case as unlimited.
|
||||||
|
long subsSwapMem = subsystem.getMemoryAndSwapLimit();
|
||||||
|
if (subsSwapMem >= totalSystemMemSwap) {
|
||||||
|
return CgroupSubsystem.LONG_RETVAL_UNLIMITED;
|
||||||
|
}
|
||||||
|
return subsSwapMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -185,5 +195,6 @@ public class CgroupMetrics implements Metrics {
|
||||||
|
|
||||||
private static native boolean isUseContainerSupport();
|
private static native boolean isUseContainerSupport();
|
||||||
private static native long getTotalMemorySize0();
|
private static native long getTotalMemorySize0();
|
||||||
|
private static native long getTotalSwapSize0();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
@ -43,3 +44,15 @@ Java_jdk_internal_platform_CgroupMetrics_getTotalMemorySize0
|
||||||
jlong page_size = sysconf(_SC_PAGESIZE);
|
jlong page_size = sysconf(_SC_PAGESIZE);
|
||||||
return pages * page_size;
|
return pages * page_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_jdk_internal_platform_CgroupMetrics_getTotalSwapSize0
|
||||||
|
(JNIEnv *env, jclass ignored)
|
||||||
|
{
|
||||||
|
struct sysinfo si;
|
||||||
|
int retval = sysinfo(&si);
|
||||||
|
if (retval < 0) {
|
||||||
|
return 0; // syinfo failed, treat as no swap
|
||||||
|
}
|
||||||
|
return (jlong)si.totalswap;
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox
|
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox
|
||||||
* @run main/othervm -Xbootclasspath/a:whitebox.jar -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestMemoryAwareness
|
* @run main/othervm -Xbootclasspath/a:whitebox.jar -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestMemoryAwareness
|
||||||
*/
|
*/
|
||||||
|
import java.util.function.Consumer;
|
||||||
import jdk.test.lib.containers.docker.Common;
|
import jdk.test.lib.containers.docker.Common;
|
||||||
import jdk.test.lib.containers.docker.DockerRunOptions;
|
import jdk.test.lib.containers.docker.DockerRunOptions;
|
||||||
import jdk.test.lib.containers.docker.DockerTestUtils;
|
import jdk.test.lib.containers.docker.DockerTestUtils;
|
||||||
|
@ -96,7 +97,9 @@ public class TestMemoryAwareness {
|
||||||
true /* additional cgroup fs mounts */
|
true /* additional cgroup fs mounts */
|
||||||
);
|
);
|
||||||
testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory();
|
testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory();
|
||||||
|
testOSMXBeanIgnoresSwapLimitExceedingPhysical();
|
||||||
testMetricsExceedingPhysicalMemory();
|
testMetricsExceedingPhysicalMemory();
|
||||||
|
testMetricsSwapExceedingPhysical();
|
||||||
testContainerMemExceedsPhysical();
|
testContainerMemExceedsPhysical();
|
||||||
} finally {
|
} finally {
|
||||||
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
|
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
|
||||||
|
@ -183,6 +186,13 @@ public class TestMemoryAwareness {
|
||||||
|
|
||||||
private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, String expectedMemory,
|
private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, String expectedMemory,
|
||||||
String swapAllocation, String expectedSwap, boolean addCgroupMounts) throws Exception {
|
String swapAllocation, String expectedSwap, boolean addCgroupMounts) throws Exception {
|
||||||
|
Consumer<OutputAnalyzer> noOp = o -> {};
|
||||||
|
testOperatingSystemMXBeanAwareness(memoryAllocation, expectedMemory, swapAllocation, expectedSwap, false, noOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, String expectedMemory,
|
||||||
|
String swapAllocation, String expectedSwap, boolean addCgroupMounts,
|
||||||
|
Consumer<OutputAnalyzer> additionalMatch) throws Exception {
|
||||||
|
|
||||||
Common.logNewTestCase("Check OperatingSystemMXBean");
|
Common.logNewTestCase("Check OperatingSystemMXBean");
|
||||||
|
|
||||||
|
@ -191,6 +201,7 @@ public class TestMemoryAwareness {
|
||||||
"--memory", memoryAllocation,
|
"--memory", memoryAllocation,
|
||||||
"--memory-swap", swapAllocation
|
"--memory-swap", swapAllocation
|
||||||
)
|
)
|
||||||
|
.addJavaOpts("-esa")
|
||||||
// CheckOperatingSystemMXBean uses Metrics (jdk.internal.platform) for
|
// CheckOperatingSystemMXBean uses Metrics (jdk.internal.platform) for
|
||||||
// diagnostics
|
// diagnostics
|
||||||
.addJavaOpts("--add-exports")
|
.addJavaOpts("--add-exports")
|
||||||
|
@ -228,9 +239,9 @@ public class TestMemoryAwareness {
|
||||||
} catch(RuntimeException ex) {
|
} catch(RuntimeException ex) {
|
||||||
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");
|
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");
|
||||||
}
|
}
|
||||||
|
additionalMatch.accept(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// JDK-8292541: Ensure OperatingSystemMXBean ignores container memory limits above the host's physical memory.
|
// JDK-8292541: Ensure OperatingSystemMXBean ignores container memory limits above the host's physical memory.
|
||||||
private static void testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory()
|
private static void testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -239,6 +250,35 @@ public class TestMemoryAwareness {
|
||||||
testOperatingSystemMXBeanAwareness(badMem, hostMaxMem, badMem, hostMaxMem);
|
testOperatingSystemMXBeanAwareness(badMem, hostMaxMem, badMem, hostMaxMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testOSMXBeanIgnoresSwapLimitExceedingPhysical()
|
||||||
|
throws Exception {
|
||||||
|
long totalSwap = wb.hostPhysicalSwap() + wb.hostPhysicalMemory();
|
||||||
|
String expectedSwap = Long.valueOf(totalSwap).toString();
|
||||||
|
String hostMaxMem = getHostMaxMemory();
|
||||||
|
String badMem = hostMaxMem + "0";
|
||||||
|
final String badSwap = expectedSwap + "0";
|
||||||
|
testOperatingSystemMXBeanAwareness(badMem, hostMaxMem, badSwap, expectedSwap, false, o -> {
|
||||||
|
o.shouldNotContain("Metrics.getMemoryAndSwapLimit() == " + badSwap);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testMetricsSwapExceedingPhysical()
|
||||||
|
throws Exception {
|
||||||
|
Common.logNewTestCase("Metrics ignore container swap memory limit exceeding physical");
|
||||||
|
long totalSwap = wb.hostPhysicalSwap() + wb.hostPhysicalMemory();
|
||||||
|
String expectedSwap = Long.valueOf(totalSwap).toString();
|
||||||
|
final String badSwap = expectedSwap + "0";
|
||||||
|
String badMem = getHostMaxMemory() + "0";
|
||||||
|
DockerRunOptions opts = Common.newOpts(imageName)
|
||||||
|
.addJavaOpts("-XshowSettings:system")
|
||||||
|
.addDockerOpts("--memory", badMem)
|
||||||
|
.addDockerOpts("--memory-swap", badSwap);
|
||||||
|
|
||||||
|
OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts);
|
||||||
|
out.shouldContain("Memory Limit: Unlimited");
|
||||||
|
out.shouldContain("Memory & Swap Limit: Unlimited");
|
||||||
|
}
|
||||||
|
|
||||||
// JDK-8292541: Ensure Metrics ignores container memory limits above the host's physical memory.
|
// JDK-8292541: Ensure Metrics ignores container memory limits above the host's physical memory.
|
||||||
private static void testMetricsExceedingPhysicalMemory()
|
private static void testMetricsExceedingPhysicalMemory()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue