Skip to content

Commit

Permalink
8296671: [JFR] jdk.ContainerConfiguration event should include host t…
Browse files Browse the repository at this point in the history
…otal memory

Reviewed-by: egahlin
  • Loading branch information
jerboaa committed Nov 24, 2022
1 parent 8b73970 commit 3c4d520
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 5 deletions.
11 changes: 11 additions & 0 deletions src/hotspot/share/jfr/jni/jfrJniMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

#ifdef LINUX
#include "osContainer_linux.hpp"
#include "os_linux.hpp"
#endif

#define NO_TRANSITION(result_type, header) extern "C" { result_type JNICALL header {
Expand Down Expand Up @@ -391,3 +392,13 @@ JVM_ENTRY_NO_ENV(jboolean, jfr_is_containerized(JNIEnv* env, jobject jvm))
return false;
#endif
JVM_END

JVM_ENTRY_NO_ENV(jlong, jfr_host_total_memory(JNIEnv* env, jobject jvm))
#ifdef LINUX
// We want the host memory, not the container limit.
// os::physical_memory() would return the container limit.
return os::Linux::physical_memory();
#else
return os::physical_memory();
#endif
JVM_END
2 changes: 2 additions & 0 deletions src/hotspot/share/jfr/jni/jfrJniMethod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ jboolean JNICALL jfr_is_class_instrumented(JNIEnv* env, jobject jvm, jclass claz

jboolean JNICALL jfr_is_containerized(JNIEnv* env, jobject jvm);

jlong JNICALL jfr_host_total_memory(JNIEnv* env, jobject jvm);

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
(char*)"getTypeId", (char*)"(Ljava/lang/String;)J", (void*)jfr_get_type_id_from_string,
(char*)"isExcluded", (char*)"(Ljava/lang/Class;)Z", (void*)jfr_is_class_excluded,
(char*)"isInstrumented", (char*)"(Ljava/lang/Class;)Z", (void*) jfr_is_class_instrumented,
(char*)"isContainerized", (char*)"()Z", (void*) jfr_is_containerized
(char*)"isContainerized", (char*)"()Z", (void*) jfr_is_containerized,
(char*)"hostTotalMemory", (char*)"()J", (void*) jfr_host_total_memory
};

const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ public final class ContainerConfigurationEvent extends AbstractJDKEvent {
@Description("Maximum amount of physical memory and swap space, in bytes, that can be allocated in the container")
@DataAmount
public long swapMemoryLimit;

@Label("Container Host Total Memory")
@Description("Total memory of the host running the container")
@DataAmount
public long hostTotalMemory;
}
6 changes: 6 additions & 0 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,10 @@ public boolean hasNativeJFR() {
* can't be emitted anyway.
*/
public native boolean isContainerized();

/**
* Returns the total amount of memory of the host system whether or not this
* JVM runs in a container.
*/
public native long hostTotalMemory();
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ private static void emitContainerConfiguration() {
t.memorySoftLimit = containerMetrics.getMemorySoftLimit();
t.memoryLimit = containerMetrics.getMemoryLimit();
t.swapMemoryLimit = containerMetrics.getMemoryAndSwapLimit();
t.hostTotalMemory = JVM.getJVM().hostTotalMemory();
t.commit();
}
}
Expand Down
25 changes: 21 additions & 4 deletions test/hotspot/jtreg/containers/docker/TestJFREvents.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class TestJFREvents {
private static final String TEST_ENV_VARIABLE = "UNIQUE_VARIABLE_ABC592903XYZ";
private static final String TEST_ENV_VALUE = "unique_value_abc592903xyz";
private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
private static final int UNKNOWN = -100;

public static void main(String[] args) throws Exception {
System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
Expand Down Expand Up @@ -82,18 +83,32 @@ public static void main(String[] args) throws Exception {
}

private static void containerInfoTestCase() throws Exception {
long hostTotalMemory = getHostTotalMemory();
System.out.println("Debug: Host total memory is " + hostTotalMemory);
// Leave one CPU for system and tools, otherwise this test may be unstable.
// Try the memory sizes that were verified by testMemory tests before.
int maxNrOfAvailableCpus = availableCPUs - 1;
for (int cpus = 1; cpus < maxNrOfAvailableCpus; cpus *= 2) {
for (int mem : new int[]{ 200, 500, 1024 }) {
testContainerInfo(cpus, mem);
testContainerInfo(cpus, mem, hostTotalMemory);
}
}
}

private static void testContainerInfo(int expectedCPUs, int expectedMemoryMB) throws Exception {
Common.logNewTestCase("ContainerInfo: --cpus = " + expectedCPUs + " --memory=" + expectedMemoryMB + "m");
private static long getHostTotalMemory() throws Exception {
DockerRunOptions opts = Common.newOpts(imageName);

String hostMem = Common.run(opts).firstMatch("total physical memory: (\\d+)", 1);
try {
return Long.parseLong(hostMem);
} catch (NumberFormatException e) {
System.out.println("Could not parse total physical memory '" + hostMem + "' returning " + UNKNOWN);
return UNKNOWN;
}
}

private static void testContainerInfo(int expectedCPUs, int expectedMemoryMB, long hostTotalMemory) throws Exception {
Common.logNewTestCase("ContainerInfo: --cpus=" + expectedCPUs + " --memory=" + expectedMemoryMB + "m");
String eventName = "jdk.ContainerConfiguration";
long expectedSlicePeriod = 100000; // default slice period
long expectedMemoryLimit = expectedMemoryMB * 1024 * 1024;
Expand All @@ -102,6 +117,7 @@ private static void testContainerInfo(int expectedCPUs, int expectedMemoryMB) th
String cpuQuotaFld = "cpuQuota";
String cpuSlicePeriodFld = "cpuSlicePeriod";
String memoryLimitFld = "memoryLimit";
String totalMem = "hostTotalMemory";

DockerTestUtils.dockerRunJava(
commonDockerOpts()
Expand All @@ -112,7 +128,8 @@ private static void testContainerInfo(int expectedCPUs, int expectedMemoryMB) th
.shouldContain(cpuCountFld + " = " + expectedCPUs)
.shouldContain(cpuSlicePeriodFld + " = " + expectedSlicePeriod)
.shouldContain(cpuQuotaFld + " = " + expectedCPUs * expectedSlicePeriod)
.shouldContain(memoryLimitFld + " = " + expectedMemoryLimit);
.shouldContain(memoryLimitFld + " = " + expectedMemoryLimit)
.shouldContain(totalMem + " = " + hostTotalMemory);
}

private static void testCpuUsage() throws Exception {
Expand Down

1 comment on commit 3c4d520

@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.