From a5122d7f6c36a4c98ea4bea7a7c8081e2a4dadca Mon Sep 17 00:00:00 2001 From: Yi-Fan Tsai Date: Mon, 18 Dec 2023 15:20:59 +0000 Subject: [PATCH] 8314029: Add file name parameter to Compiler.perfmap Reviewed-by: cjplummer, eastigeevich --- src/hotspot/share/code/codeCache.cpp | 14 ++++++---- src/hotspot/share/code/codeCache.hpp | 2 +- .../share/services/diagnosticCommand.cpp | 9 +++++- .../share/services/diagnosticCommand.hpp | 7 +++-- src/jdk.jcmd/share/man/jcmd.1 | 12 +++++++- .../dcmd/compiler/PerfMapTest.java | 28 +++++++++++++------ 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 9b10dab2ef7..8018604af60 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1819,16 +1819,20 @@ void CodeCache::log_state(outputStream* st) { } #ifdef LINUX -void CodeCache::write_perf_map() { +void CodeCache::write_perf_map(const char* filename) { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - // Perf expects to find the map file at /tmp/perf-.map. + // Perf expects to find the map file at /tmp/perf-.map + // if the file name is not specified. char fname[32]; - jio_snprintf(fname, sizeof(fname), "/tmp/perf-%d.map", os::current_process_id()); + if (filename == nullptr) { + jio_snprintf(fname, sizeof(fname), "/tmp/perf-%d.map", os::current_process_id()); + filename = fname; + } - fileStream fs(fname, "w"); + fileStream fs(filename, "w"); if (!fs.is_open()) { - log_warning(codecache)("Failed to create %s for perf map", fname); + log_warning(codecache)("Failed to create %s for perf map", filename); return; } diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 5418a29e58f..103268c8ffc 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -227,7 +227,7 @@ class CodeCache : AllStatic { static void print_trace(const char* event, CodeBlob* cb, uint size = 0) PRODUCT_RETURN; static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); - LINUX_ONLY(static void write_perf_map();) + LINUX_ONLY(static void write_perf_map(const char* filename = nullptr);) static const char* get_code_heap_name(CodeBlobType code_blob_type) { return (heap_available(code_blob_type) ? get_code_heap(code_blob_type)->name() : "Unused"); } static void report_codemem_full(CodeBlobType code_blob_type, bool print); diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index bf9f9f02573..7a0befac3a1 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -851,8 +851,15 @@ void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { } #ifdef LINUX +PerfMapDCmd::PerfMapDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _filename("filename", "Name of the map file", "STRING", false) +{ + _dcmdparser.add_dcmd_argument(&_filename); +} + void PerfMapDCmd::execute(DCmdSource source, TRAPS) { - CodeCache::write_perf_map(); + CodeCache::write_perf_map(_filename.value()); } #endif // LINUX diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index 395212a204e..88a48970810 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -577,9 +577,12 @@ public: }; #ifdef LINUX -class PerfMapDCmd : public DCmd { +class PerfMapDCmd : public DCmdWithParser { +protected: + DCmdArgument _filename; public: - PerfMapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static int num_arguments() { return 1; } + PerfMapDCmd(outputStream* output, bool heap); static const char* name() { return "Compiler.perfmap"; } diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index f33f7d2cb1e..6d1c5cd008d 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -178,11 +178,21 @@ Prints all compiled methods in code cache that are alive. Impact: Medium .RE .TP -\f[V]Compiler.perfmap\f[R] (Linux only) +\f[V]Compiler.perfmap\f[R] [\f[I]arguments\f[R]] (Linux only) Write map file for Linux perf tool. .RS .PP Impact: Low +.PP +\f[I]arguments\f[R]: +.IP \[bu] 2 +\f[V]filename\f[R]: (Optional) Name of the map file (STRING, no default +value) +.PP +If \f[V]filename\f[R] is not specified, a default file name is chosen +using the pid of the target JVM process. +For example, if the pid is \f[V]12345\f[R], then the default +\f[V]filename\f[R] will be \f[V]/tmp/perf-12345.map\f[R]. .RE .TP \f[V]Compiler.queue\f[R] diff --git a/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java index f4da5e979e3..ef05468bc29 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, Arm Limited. All rights reserved. + * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2023, Arm Limited. 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 @@ -46,6 +46,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -58,15 +59,12 @@ public class PerfMapTest { static final Pattern LINE_PATTERN = Pattern.compile("^((?:0x)?\\p{XDigit}+)\\s+((?:0x)?\\p{XDigit}+)\\s+(.*)$"); - public void run(CommandExecutor executor) { - OutputAnalyzer output = executor.execute("Compiler.perfmap"); + public void run(CommandExecutor executor, String cmd, Path path) { + OutputAnalyzer output = executor.execute(cmd); output.stderrShouldBeEmpty(); output.stdoutShouldBeEmpty(); - final long pid = ProcessHandle.current().pid(); - final Path path = Paths.get(String.format("/tmp/perf-%d.map", pid)); - Assert.assertTrue(Files.exists(path)); // Sanity check the file contents @@ -81,7 +79,19 @@ public class PerfMapTest { } @Test - public void jmx() { - run(new JMXExecutor()); + public void defaultMapFile() { + final long pid = ProcessHandle.current().pid(); + final Path path = Paths.get(String.format("/tmp/perf-%d.map", pid)); + run(new JMXExecutor(), "Compiler.perfmap", path); + } + + @Test + public void specifiedMapFile() { + String test_dir = System.getProperty("test.dir", "."); + Path path = null; + do { + path = Paths.get(String.format("%s/%s.map", test_dir, UUID.randomUUID().toString())); + } while(Files.exists(path)); + run(new JMXExecutor(), "Compiler.perfmap " + path.toString(), path); } }