Skip to content

Commit

Permalink
dump nmt on signal
Browse files Browse the repository at this point in the history
  • Loading branch information
roberttoyonaga committed May 2, 2024
1 parent ee40fc1 commit 1316630
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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;

import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.heap.dump.HeapDumping;
import com.oracle.svm.core.nmt.NativeMemoryTracking;
import java.io.IOException;

import jdk.internal.misc.Signal;

public class Sigusr1Handler implements Signal.Handler {
static boolean installed;

/**
* Depending on which features are included in the image, this method may be called multiple
* times by the thread executing startup hooks.
*/
public static void install() {
if (!installed) {
installed = true;
Signal.handle(new Signal("USR1"), new Sigusr1Handler());
}
}

@Override
public void handle(Signal arg0) {
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
try {
NativeMemoryTracking.singleton().dumpReport();
} catch (IOException e) {
Log.log().string("IOException during NMT report dump: ").string(e.getMessage()).newline();
}
}

if (VMInspectionOptions.hasHeapDumpSupport()) {
try {
HeapDumping.singleton().dumpHeap(true);
} catch (IOException e) {
Log.log().string("IOException during dumpHeap: ").string(e.getMessage()).newline();
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionType;

import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.Immutable;

public final class VMInspectionOptions {
private static final String ENABLE_MONITORING_OPTION = "enable-monitoring";
private static final String MONITORING_DEFAULT_NAME = "<deprecated-default>";
Expand Down Expand Up @@ -83,6 +85,11 @@ public final class VMInspectionOptions {
@Option(help = "Print native memory tracking statistics on shutdown if native memory tracking is enabled.", type = OptionType.User) //
public static final RuntimeOptionKey<Boolean> PrintNMTStatistics = new RuntimeOptionKey<>(false);

@Option(help = "Path of the file or directory in which NMT report dumps are created. An empty value means a default file " +
"name will be used. An existing directory means the dump will be placed in the directory and have " +
"the default file name.") //
public static final RuntimeOptionKey<String> NmtDumpPath = new RuntimeOptionKey<>("", Immutable);

@Platforms(Platform.HOSTED_ONLY.class)
public static void validateEnableMonitoringFeatures(@SuppressWarnings("unused") OptionKey<?> optionKey) {
Set<String> enabledFeatures = getEnabledMonitoringFeatures();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,20 @@
*/
package com.oracle.svm.core.heap.dump;

import java.io.IOException;

import com.oracle.svm.core.Sigusr1Handler;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.jdk.RuntimeSupport;
import com.oracle.svm.core.log.Log;

import jdk.internal.misc.Signal;

public class HeapDumpStartupHook implements RuntimeSupport.Hook {
@Override
public void execute(boolean isFirstIsolate) {
if (isFirstIsolate && SubstrateOptions.EnableSignalHandling.getValue()) {
DumpHeapReport.install();
Sigusr1Handler.install();
}

if (SubstrateOptions.HeapDumpOnOutOfMemoryError.getValue()) {
HeapDumping.singleton().initializeDumpHeapOnOutOfMemoryError();
}
}
}

class DumpHeapReport implements Signal.Handler {
static void install() {
Signal.handle(new Signal("USR1"), new DumpHeapReport());
}

@Override
public void handle(Signal arg0) {
try {
HeapDumping.singleton().dumpHeap(true);
} catch (IOException e) {
Log.log().string("IOException during dumpHeap: ").string(e.getMessage()).newline();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
Expand Down Expand Up @@ -28,9 +28,12 @@

import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;

import com.oracle.svm.core.Sigusr1Handler;
import com.oracle.svm.core.SubstrateOptions;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.ProcessProperties;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;
Expand All @@ -45,6 +48,11 @@

import jdk.graal.compiler.api.replacements.Fold;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
* This class implements native memory tracking (NMT). There are two components to NMT: tracking
* memory allocations (malloc/realloc/calloc), and tracking virtual memory usage (not supported
Expand Down Expand Up @@ -197,28 +205,66 @@ private NmtMallocMemoryInfo getInfo(int category) {
return categories[category];
}

public static RuntimeSupport.Hook startupHook() {
return isFirstIsolate -> {
if (isFirstIsolate && SubstrateOptions.EnableSignalHandling.getValue()) {
Sigusr1Handler.install();
}
};
}

public static RuntimeSupport.Hook shutdownHook() {
return isFirstIsolate -> NativeMemoryTracking.singleton().printStatistics();
}

private void printStatistics() {
public void printStatistics() {
if (VMInspectionOptions.PrintNMTStatistics.getValue()) {
System.out.println();
System.out.println("Native memory tracking");
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();
NmtMallocMemoryInfo info = getInfo(i);

System.out.println(" " + name + " peak used memory: " + info.getPeakUsed() + " bytes");
System.out.println(" " + name + " alive allocations at peak: " + info.getCountAtPeakUsage());
System.out.println(" " + name + " currently used memory: " + info.getUsed() + " bytes");
System.out.println(" " + name + " currently alive allocations: " + info.getCount());
}
System.out.println(generateReportString());
}
}

public void dumpReport() throws IOException {
String path = reportPath();
FileWriter writer = new FileWriter(path);
writer.write(generateReportString());
writer.close();

}

private static String reportPath() {
String time = Long.toString(System.currentTimeMillis());
String pid = Long.toString(ProcessProperties.getProcessID());
String defaultFilename = "nmt_report_" + pid + "_" + time + ".txt";

String filenameOrDirectory = VMInspectionOptions.NmtDumpPath.getValue();
if (filenameOrDirectory.isEmpty()) {
return defaultFilename;
}
var targetPath = Paths.get(filenameOrDirectory);
if (Files.isDirectory(targetPath)) {
targetPath = targetPath.resolve(defaultFilename);
}
return targetPath.toFile().getAbsolutePath();
}

private String generateReportString() {
StringBuilder stringBuilder = new StringBuilder(2500);
stringBuilder.append("\n");
stringBuilder.append("Native memory tracking\n");
stringBuilder.append(" Peak total used memory: " + getPeakTotalUsedMemory() + " bytes\n");
stringBuilder.append(" Total alive allocations at peak usage: " + getCountAtTotalPeakUsage() + "\n");
stringBuilder.append(" Total used memory: " + getTotalUsedMemory() + " bytes\n");
stringBuilder.append(" Total alive allocations: " + getTotalCount() + "\n");

for (int i = 0; i < NmtCategory.values().length; i++) {
String name = NmtCategory.values()[i].getName();
NmtMallocMemoryInfo info = getInfo(i);

stringBuilder.append(" " + name + " peak used memory: " + info.getPeakUsed() + " bytes\n");
stringBuilder.append(" " + name + " alive allocations at peak: " + info.getCountAtPeakUsage() + "\n");
stringBuilder.append(" " + name + " currently used memory: " + info.getUsed() + " bytes\n");
stringBuilder.append(" " + name + " currently alive allocations: " + info.getCount() + "\n");
}
return stringBuilder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public void afterRegistration(AfterRegistrationAccess access) {

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(NativeMemoryTracking.startupHook());
RuntimeSupport.getRuntimeSupport().addShutdownHook(NativeMemoryTracking.shutdownHook());
}
}

0 comments on commit 1316630

Please sign in to comment.