Skip to content

Commit

Permalink
add NMT peak events
Browse files Browse the repository at this point in the history
  • Loading branch information
roberttoyonaga committed Mar 1, 2024
1 parent 8ef5550 commit 2bc5cdf
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,37 @@ private static void emitClassLoadingStatistics() {
}
}

private static void emitNativeMemoryTrackingEvents() {
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
emitNativeMemoryTrackingEvents0(NmtCategory.values());
}
}

/**
* Emit events for NativeMemoryUsage and NativeMemoryUsageTotal. We do not guarantee consistent
* measurements across NMT categories and the total. Each individual NMT category uses atomic
* counters which may change while we are in this method. Similar to OpenJDK, it is only a
* best-effort approach.
*/
private static void emitNativeMemoryTrackingEvents() {
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
/* All NMT events should have a consistent timestamp. */
long timestamp = JfrTicks.elapsedTicks();
emitNativeMemoryTrackingEvents0(NmtCategory.values(), timestamp);

NativeMemoryUsageTotalPeakEvent nmtTotalPeakEvent = new NativeMemoryUsageTotalPeakEvent();
nmtTotalPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtTotalPeakUsage();
nmtTotalPeakEvent.peakUsage = NativeMemoryTracking.singleton().getPeakTotalUsedMemory();
nmtTotalPeakEvent.commit();

for (NmtCategory nmtCategory : NmtCategory.values()) {
NativeMemoryUsagePeakEvent nmtPeakEvent = new NativeMemoryUsagePeakEvent();
nmtPeakEvent.type = nmtCategory.getName();
nmtPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtPeakUsage(nmtCategory);
nmtPeakEvent.peakUsage = NativeMemoryTracking.singleton().getPeakUsedMemory(nmtCategory);
nmtPeakEvent.commit();
}
}
}

@Uninterruptible(reason = "Accesses a JFR buffer.")
private static void emitNativeMemoryTrackingEvents0(NmtCategory[] nmtCategories) {
private static void emitNativeMemoryTrackingEvents0(NmtCategory[] nmtCategories, long timestamp) {
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
/* All NMT events should have a consistent timestamp. */
long timestamp = JfrTicks.elapsedTicks();

if (JfrEvent.NativeMemoryUsage.shouldEmit()) {
for (NmtCategory nmtCategory : nmtCategories) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.jfr.events;

import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;

@Name("svm.NativeMemoryUsagePeak")
@Label("Native Memory Usage Peak")
@Description("Information about native memory peak usage of committed virtual memory and malloc.")
@Category("Native Image")
@StackTrace(false)
public class NativeMemoryUsagePeakEvent extends Event {
@Label("Memory Type") public String type;
@Label("Peak Usage") public long peakUsage;
@Label("CountAtPeak") public long countAtPeak;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.jfr.events;

import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;

@Name("svm.NativeMemoryUsageTotalPeak")
@Label("Native Memory Usage Total Peak")
@Description("Information about native memory peak usage")
@Category("Native Image")
@StackTrace(false)
public class NativeMemoryUsageTotalPeakEvent extends Event {
@Label("PeakUsage") public long peakUsage;
@Label("CountAtPeak") public long countAtPeak;
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,36 @@ public long getUsedMemory(NmtCategory category) {
return mallocMemorySnapshot.getInfoByCategory(category).getUsed();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getPeakUsedMemory(NmtCategory category) {
return mallocMemorySnapshot.getInfoByCategory(category).getPeakUsed();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getCountAtPeakUsage(NmtCategory category) {
return mallocMemorySnapshot.getInfoByCategory(category).getCountAtPeakUsage();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getTotalCount() {
return mallocMemorySnapshot.getTotalInfo().getCount();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getTotalUsedMemory() {
return mallocMemorySnapshot.getTotalInfo().getUsed();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getPeakTotalUsedMemory() {
return mallocMemorySnapshot.getTotalInfo().getPeakUsed();
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getCountAtTotalPeakUsage() {
return mallocMemorySnapshot.getTotalInfo().getCountAtPeakUsage();
}

public static RuntimeSupport.Hook shutdownHook() {
return isFirstIsolate -> NativeMemoryTracking.singleton().printStatistics();
}
Expand All @@ -162,10 +187,10 @@ public void printStatistics() {
if (VMInspectionOptions.PrintNMTStatistics.getValue()) {
System.out.println();
System.out.println("Native memory tracking");
System.out.println(" Peak total used memory: " + mallocMemorySnapshot.getTotalInfo().getPeakUsed() + " bytes");
System.out.println(" Total alive allocations at peak usage: " + mallocMemorySnapshot.getTotalInfo().getCountAtPeakUsage());
System.out.println(" Total used memory: " + mallocMemorySnapshot.getTotalInfo().getUsed() + " bytes");
System.out.println(" Total alive allocations: " + mallocMemorySnapshot.getTotalInfo().getCount());
System.out.println(" Peak total used memory: " + getPeakTotalUsedMemory() + " bytes");
System.out.println(" Total alive allocations at peak usage: " + getCountAtTotalPeakUsage());
System.out.println(" Total used memory: " + getTotalUsedMemory() + " bytes");
System.out.println(" Total alive allocations: " + getTotalCount());

for (int i = 0; i < NmtCategory.values().length; i++) {
String name = NmtCategory.values()[i].getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ public class TestNmtEvents extends JfrRecordingTest {

@Test
public void test() throws Throwable {
String[] events = new String[]{JfrEvent.NativeMemoryUsage.getName(), JfrEvent.NativeMemoryUsageTotal.getName()};
String[] events = new String[]{
JfrEvent.NativeMemoryUsage.getName(),
JfrEvent.NativeMemoryUsageTotal.getName(),
"svm.NativeMemoryUsageTotalPeak",
"svm.NativeMemoryUsagePeak"
};

Recording recording = startRecording(events);

Pointer ptr = NativeMemory.malloc(WordFactory.unsigned(ALLOCATION_SIZE), NmtCategory.Code);
Expand All @@ -62,18 +68,29 @@ public void test() throws Throwable {
private static void validateEvents(List<RecordedEvent> events) {
boolean foundNativeMemoryUsage = false;
boolean foundNativeMemoryUsageTotal = false;
boolean foundNativeMemoryUsageTotalPeak = false;
boolean foundNativeMemoryUsagePeak = false;

assertTrue(events.size() >= 2);
assertTrue(events.size() >= 4);
for (RecordedEvent e : events) {
if (e.getEventType().getName().equals(JfrEvent.NativeMemoryUsage.getName())) {
if (e.getString("type").equals(NmtCategory.Code.getName())) {
foundNativeMemoryUsage = true;
}
if (e.getEventType().getName().equals(JfrEvent.NativeMemoryUsage.getName()) &&
e.getString("type").equals(NmtCategory.Code.getName())) {
foundNativeMemoryUsage = true;

}
if (e.getEventType().getName().equals("svm.NativeMemoryUsageTotalPeak")) {
foundNativeMemoryUsageTotalPeak = true;
}
if (e.getEventType().getName().equals("svm.NativeMemoryUsagePeak") &&
e.getString("type").equals(NmtCategory.Code.getName())) {
foundNativeMemoryUsagePeak = true;
} else if (e.getEventType().getName().equals(JfrEvent.NativeMemoryUsageTotal.getName())) {
foundNativeMemoryUsageTotal = true;
}
}
assertTrue(foundNativeMemoryUsage);
assertTrue(foundNativeMemoryUsageTotal);
assertTrue(foundNativeMemoryUsagePeak);
assertTrue(foundNativeMemoryUsageTotalPeak);
}
}

0 comments on commit 2bc5cdf

Please sign in to comment.