From 97d71ea79e4eb5bc9f78a473b94926d18e3c1c5e Mon Sep 17 00:00:00 2001 From: tstuefe Date: Wed, 16 Jun 2021 14:34:49 +0200 Subject: [PATCH 1/4] start --- src/hotspot/os/linux/os_linux.cpp | 55 ++++++++------ src/hotspot/os/linux/os_linux.hpp | 17 +++++ src/hotspot/os/linux/trimCHeapDCmd.cpp | 74 +++++++++++++++++++ src/hotspot/os/linux/trimCHeapDCmd.hpp | 52 +++++++++++++ .../share/services/diagnosticCommand.cpp | 5 +- .../dcmd/vm/TrimLibcHeapTest.java | 52 +++++++++++++ 6 files changed, 230 insertions(+), 25 deletions(-) create mode 100644 src/hotspot/os/linux/trimCHeapDCmd.cpp create mode 100644 src/hotspot/os/linux/trimCHeapDCmd.hpp create mode 100644 test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index a3424322be86c..de1f5d3aa2df4 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2137,44 +2137,51 @@ void os::Linux::print_system_memory_info(outputStream* st) { "/sys/kernel/mm/transparent_hugepage/defrag", st); } -void os::Linux::print_process_memory_info(outputStream* st) { - - st->print_cr("Process Memory:"); - - // Print virtual and resident set size; peak values; swap; and for - // rss its components if the kernel is recent enough. - ssize_t vmsize = -1, vmpeak = -1, vmswap = -1, - vmrss = -1, vmhwm = -1, rssanon = -1, rssfile = -1, rssshmem = -1; +bool os::Linux::query_memory_info(os::Linux::meminfo_t* info) { + FILE* f = ::fopen("/proc/self/status", "r"); const int num_values = 8; int num_found = 0; - FILE* f = ::fopen("/proc/self/status", "r"); char buf[256]; + info->vmsize = info->vmpeak = info->vmrss = info->vmhwm = info->vmswap = + info->rssanon = info->rssfile = info->rssshmem = -1; if (f != NULL) { while (::fgets(buf, sizeof(buf), f) != NULL && num_found < num_values) { - if ( (vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &vmsize) == 1) || - (vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &vmpeak) == 1) || - (vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &vmswap) == 1) || - (vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &vmhwm) == 1) || - (vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &vmrss) == 1) || - (rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &rssanon) == 1) || - (rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &rssfile) == 1) || - (rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &rssshmem) == 1) + if ( (info->vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &info->vmsize) == 1) || + (info->vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &info->vmpeak) == 1) || + (info->vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &info->vmswap) == 1) || + (info->vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &info->vmhwm) == 1) || + (info->vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &info->vmrss) == 1) || + (info->rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &info->rssanon) == 1) || + (info->rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &info->rssfile) == 1) || + (info->rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &info->rssshmem) == 1) ) { num_found ++; } } fclose(f); + return true; + } + return false; +} + +void os::Linux::print_process_memory_info(outputStream* st) { - st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmsize, vmpeak); - st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmrss, vmhwm); - if (rssanon != -1) { // requires kernel >= 4.5 + st->print_cr("Process Memory:"); + + // Print virtual and resident set size; peak values; swap; and for + // rss its components if the kernel is recent enough. + meminfo_t info; + if (query_memory_info(&info)) { + st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmsize, info.vmpeak); + st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmrss, info.vmhwm); + if (info.rssanon != -1) { // requires kernel >= 4.5 st->print(" (anon: " SSIZE_FORMAT "K, file: " SSIZE_FORMAT "K, shmem: " SSIZE_FORMAT "K)", - rssanon, rssfile, rssshmem); + info.rssanon, info.rssfile, info.rssshmem); } st->cr(); - if (vmswap != -1) { // requires kernel >= 2.6.34 - st->print_cr("Swapped out: " SSIZE_FORMAT "K", vmswap); + if (info.vmswap != -1) { // requires kernel >= 2.6.34 + st->print_cr("Swapped out: " SSIZE_FORMAT "K", info.vmswap); } } else { st->print_cr("Could not open /proc/self/status to get process memory related information"); @@ -2195,7 +2202,7 @@ void os::Linux::print_process_memory_info(outputStream* st) { struct glibc_mallinfo mi = _mallinfo(); total_allocated = (size_t)(unsigned)mi.uordblks; // Since mallinfo members are int, glibc values may have wrapped. Warn about this. - might_have_wrapped = (vmrss * K) > UINT_MAX && (vmrss * K) > (total_allocated + UINT_MAX); + might_have_wrapped = (info.vmrss * K) > UINT_MAX && (info.vmrss * K) > (total_allocated + UINT_MAX); } if (_mallinfo2 != NULL || _mallinfo != NULL) { st->print_cr("C-Heap outstanding allocations: " SIZE_FORMAT "K%s", diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index ada8db6977ea0..2f93c13179d69 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -174,6 +174,23 @@ class Linux { // Return the namespace pid if so, otherwise -1. static int get_namespace_pid(int vmid); + // Output structure for query_memory_info() + struct meminfo_t { + ssize_t vmsize; // current virtual size + ssize_t vmpeak; // peak virtual size + ssize_t vmrss; // current resident set size + ssize_t vmhwm; // peak resident set size + ssize_t vmswap; // swapped out + ssize_t rssanon; // resident set size + ssize_t rssfile; // resident set size + ssize_t rssshmem; // resident set size + }; + + // Attempts to query memory information about the current process and return it in the output structure. + // May fail (returns false) or succeed (returns true) but not all output fields are available; unavailable + // fields will contain -1. + static bool query_memory_info(meminfo_t* info); + // Stack repair handling // none present diff --git a/src/hotspot/os/linux/trimCHeapDCmd.cpp b/src/hotspot/os/linux/trimCHeapDCmd.cpp new file mode 100644 index 0000000000000..4ce0b53a6a0b1 --- /dev/null +++ b/src/hotspot/os/linux/trimCHeapDCmd.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. 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. + * + * 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. + * + */ + +#include "precompiled.hpp" +#include "logging/log.hpp" +#include "runtime/os.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" +#include "trimCHeapDCmd.hpp" + +#include + +void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) { +#ifdef __GLIBC__ + stringStream ss_report(1024); // Note: before calling trim + + // Query memory before... + os::Linux::meminfo_t info1; + os::Linux::meminfo_t info2; + bool have_info1 = os::Linux::query_memory_info(&info1); + + _output->print_cr("Attempting trim..."); + ::malloc_trim(0); + _output->print_cr("Done."); + + // ...and after trim. + bool have_info2 = os::Linux::query_memory_info(&info2); + + // Print report both to output stream as well to UL + if (have_info1 && have_info2) { + if (info1.vmsize != -1 && info2.vmsize != -1) { + ss_report.print_cr("Virtual size before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", + info1.vmsize, info2.vmsize, (info2.vmsize - info1.vmsize)); + } + if (info1.vmrss != -1 && info2.vmrss != -1) { + ss_report.print_cr("RSS before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", + info1.vmrss, info2.vmrss, (info2.vmrss - info1.vmrss)); + } + if (info1.vmswap != -1 && info2.vmswap != -1) { + ss_report.print_cr("Swap before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", + info1.vmswap, info2.vmswap, (info2.vmswap - info1.vmswap)); + } + } else { + ss_report.print_raw("No details available."); + } + _output->print_raw(ss_report.base()); + log_info(os)("malloc_trim: "); + log_info(os)("%s", ss_report.base()); +#else + _output->print_cr("Not available."); +#endif +} diff --git a/src/hotspot/os/linux/trimCHeapDCmd.hpp b/src/hotspot/os/linux/trimCHeapDCmd.hpp new file mode 100644 index 0000000000000..e9d2b4b32d3d1 --- /dev/null +++ b/src/hotspot/os/linux/trimCHeapDCmd.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. 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. + * + * 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. + * + */ + +#ifndef OS_LINUX_TRIMCHEAPDCMD_HPP +#define OS_LINUX_TRIMCHEAPDCMD_HPP + +#include "services/diagnosticCommand.hpp" + +class outputStream; + +class TrimCLibcHeapDCmd : public DCmd { +public: + TrimCLibcHeapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "VM.trim_libc_heap"; + } + static const char* description() { + return "Attempts to free up memory by trimming the glibc heap."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = { "java.lang.management.ManagementPermission", "control", NULL }; + return p; + } + virtual void execute(DCmdSource source, TRAPS); +}; + +#endif // OS_LINUX_TRIMCHEAPDCMD_HPP diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 7fad4198d17a1..e519f119e04d3 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -58,7 +58,9 @@ #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" #include "utilities/macros.hpp" - +#ifdef LINUX +#include "trimCHeapDCmd.hpp" +#endif static void loadAgentModule(TRAPS) { ResourceMark rm(THREAD); @@ -94,6 +96,7 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + LINUX_ONLY(DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));) #if INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java new file mode 100644 index 0000000000000..2621a52569e36 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.JMXExecutor; +import jdk.test.lib.process.OutputAnalyzer; + +/* + * @test + * @summary Test of diagnostic command VM.trim_libc_heap + * @library /test/lib + * @requires os.family == "linux" + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run testng TrimLibcHeapTest + */ +public class TrimLibcHeapTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("VM.trim_libc_heap"); + output.reportDiagnosticSummary(); + output.shouldMatch("(Done|Not available)"); + } + + @Test + public void jmx() { + run(new JMXExecutor()); + } +} From a48791e49e75fc2d2cdf049c9233312f7b83be35 Mon Sep 17 00:00:00 2001 From: tstuefe Date: Thu, 17 Jun 2021 10:49:03 +0200 Subject: [PATCH 2/4] Feedback Severin; renamed query function --- src/hotspot/os/linux/os_linux.cpp | 4 ++-- src/hotspot/os/linux/os_linux.hpp | 10 +++++----- src/hotspot/os/linux/trimCHeapDCmd.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index de1f5d3aa2df4..6b475c2546dea 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2137,7 +2137,7 @@ void os::Linux::print_system_memory_info(outputStream* st) { "/sys/kernel/mm/transparent_hugepage/defrag", st); } -bool os::Linux::query_memory_info(os::Linux::meminfo_t* info) { +bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { FILE* f = ::fopen("/proc/self/status", "r"); const int num_values = 8; int num_found = 0; @@ -2172,7 +2172,7 @@ void os::Linux::print_process_memory_info(outputStream* st) { // Print virtual and resident set size; peak values; swap; and for // rss its components if the kernel is recent enough. meminfo_t info; - if (query_memory_info(&info)) { + if (query_process_memory_info(&info)) { st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmsize, info.vmpeak); st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmrss, info.vmhwm); if (info.rssanon != -1) { // requires kernel >= 4.5 diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 2f93c13179d69..692dae042abda 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -174,22 +174,22 @@ class Linux { // Return the namespace pid if so, otherwise -1. static int get_namespace_pid(int vmid); - // Output structure for query_memory_info() + // Output structure for query_process_memory_info() struct meminfo_t { ssize_t vmsize; // current virtual size ssize_t vmpeak; // peak virtual size ssize_t vmrss; // current resident set size ssize_t vmhwm; // peak resident set size ssize_t vmswap; // swapped out - ssize_t rssanon; // resident set size - ssize_t rssfile; // resident set size - ssize_t rssshmem; // resident set size + ssize_t rssanon; // resident set size (anonymous mappings, needs 4.5) + ssize_t rssfile; // resident set size (file mappings, needs 4.5) + ssize_t rssshmem; // resident set size (shared mappings, needs 4.5) }; // Attempts to query memory information about the current process and return it in the output structure. // May fail (returns false) or succeed (returns true) but not all output fields are available; unavailable // fields will contain -1. - static bool query_memory_info(meminfo_t* info); + static bool query_process_memory_info(meminfo_t* info); // Stack repair handling diff --git a/src/hotspot/os/linux/trimCHeapDCmd.cpp b/src/hotspot/os/linux/trimCHeapDCmd.cpp index 4ce0b53a6a0b1..3879237fd4b1e 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.cpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.cpp @@ -39,14 +39,14 @@ void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) { // Query memory before... os::Linux::meminfo_t info1; os::Linux::meminfo_t info2; - bool have_info1 = os::Linux::query_memory_info(&info1); + bool have_info1 = os::Linux::query_process_memory_info(&info1); _output->print_cr("Attempting trim..."); ::malloc_trim(0); _output->print_cr("Done."); // ...and after trim. - bool have_info2 = os::Linux::query_memory_info(&info2); + bool have_info2 = os::Linux::query_process_memory_info(&info2); // Print report both to output stream as well to UL if (have_info1 && have_info2) { From 29807b262d51058c6738717e094265efccb69155 Mon Sep 17 00:00:00 2001 From: tstuefe Date: Fri, 25 Jun 2021 08:18:32 +0200 Subject: [PATCH 3/4] Volker feedback --- src/hotspot/os/linux/os_linux.cpp | 8 ++++---- src/hotspot/os/linux/trimCHeapDCmd.cpp | 13 +++++++++---- src/hotspot/os/linux/trimCHeapDCmd.hpp | 4 ++-- src/hotspot/share/services/diagnosticCommand.cpp | 2 +- .../serviceability/dcmd/vm/TrimLibcHeapTest.java | 7 +++++-- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 6b475c2546dea..7e4225d60b76f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2139,7 +2139,7 @@ void os::Linux::print_system_memory_info(outputStream* st) { bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { FILE* f = ::fopen("/proc/self/status", "r"); - const int num_values = 8; + const int num_values = sizeof(os::Linux::meminfo_t) / sizeof(size_t); int num_found = 0; char buf[256]; info->vmsize = info->vmpeak = info->vmrss = info->vmhwm = info->vmswap = @@ -2151,9 +2151,9 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { (info->vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &info->vmswap) == 1) || (info->vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &info->vmhwm) == 1) || (info->vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &info->vmrss) == 1) || - (info->rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &info->rssanon) == 1) || - (info->rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &info->rssfile) == 1) || - (info->rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &info->rssshmem) == 1) + (info->rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &info->rssanon) == 1) || // Needs Linux 4.5 + (info->rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &info->rssfile) == 1) || // Needs Linux 4.5 + (info->rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &info->rssshmem) == 1) // Needs Linux 4.5 ) { num_found ++; diff --git a/src/hotspot/os/linux/trimCHeapDCmd.cpp b/src/hotspot/os/linux/trimCHeapDCmd.cpp index 3879237fd4b1e..ee93ac5e8c8d7 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.cpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.cpp @@ -36,9 +36,9 @@ void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) { #ifdef __GLIBC__ stringStream ss_report(1024); // Note: before calling trim - // Query memory before... os::Linux::meminfo_t info1; os::Linux::meminfo_t info2; + // Query memory before... bool have_info1 = os::Linux::query_process_memory_info(&info1); _output->print_cr("Attempting trim..."); @@ -49,25 +49,30 @@ void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) { bool have_info2 = os::Linux::query_process_memory_info(&info2); // Print report both to output stream as well to UL + bool wrote_something = false; if (have_info1 && have_info2) { if (info1.vmsize != -1 && info2.vmsize != -1) { ss_report.print_cr("Virtual size before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", info1.vmsize, info2.vmsize, (info2.vmsize - info1.vmsize)); + wrote_something = true; } if (info1.vmrss != -1 && info2.vmrss != -1) { ss_report.print_cr("RSS before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", info1.vmrss, info2.vmrss, (info2.vmrss - info1.vmrss)); + wrote_something = true; } if (info1.vmswap != -1 && info2.vmswap != -1) { ss_report.print_cr("Swap before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)", info1.vmswap, info2.vmswap, (info2.vmswap - info1.vmswap)); + wrote_something = true; } - } else { + } + if (!wrote_something) { ss_report.print_raw("No details available."); } + _output->print_raw(ss_report.base()); - log_info(os)("malloc_trim: "); - log_info(os)("%s", ss_report.base()); + log_info(os)("malloc_trim:\n%s", ss_report.base()); #else _output->print_cr("Not available."); #endif diff --git a/src/hotspot/os/linux/trimCHeapDCmd.hpp b/src/hotspot/os/linux/trimCHeapDCmd.hpp index e9d2b4b32d3d1..3fe6375efdb53 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.hpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.hpp @@ -34,10 +34,10 @@ class TrimCLibcHeapDCmd : public DCmd { public: TrimCLibcHeapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} static const char* name() { - return "VM.trim_libc_heap"; + return "System.glibc_trim_heap"; } static const char* description() { - return "Attempts to free up memory by trimming the glibc heap."; + return "Attempts to free up memory by trimming the glibc C-heap."; } static const char* impact() { return "Low"; diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index d8de7e9a87efb..f11026fe2f77b 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -96,7 +96,6 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - LINUX_ONLY(DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));) #if INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); @@ -121,6 +120,7 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #ifdef LINUX DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #endif // LINUX DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java index 2621a52569e36..c79b35a12be6e 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java @@ -40,9 +40,12 @@ */ public class TrimLibcHeapTest { public void run(CommandExecutor executor) { - OutputAnalyzer output = executor.execute("VM.trim_libc_heap"); + OutputAnalyzer output = executor.execute("System.glibc_trim_heap"); output.reportDiagnosticSummary(); - output.shouldMatch("(Done|Not available)"); + output.shouldMatch("(Done|Not available)"); // Not available could happen on Linux + non-glibc (eg. muslc) + if (output.firstMatch("Done") != null) { + output.shouldMatch("(Virtual size before|RSS before|Swap before|No details available)"); + } } @Test From c3f055a17c93e2427ffbbc8a1b4220cb54442724 Mon Sep 17 00:00:00 2001 From: tstuefe Date: Fri, 9 Jul 2021 06:51:52 +0200 Subject: [PATCH 4/4] Rename command (see CSR) --- src/hotspot/os/linux/trimCHeapDCmd.hpp | 4 ++-- .../jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/os/linux/trimCHeapDCmd.hpp b/src/hotspot/os/linux/trimCHeapDCmd.hpp index 3fe6375efdb53..4c5b5cc2219ca 100644 --- a/src/hotspot/os/linux/trimCHeapDCmd.hpp +++ b/src/hotspot/os/linux/trimCHeapDCmd.hpp @@ -34,10 +34,10 @@ class TrimCLibcHeapDCmd : public DCmd { public: TrimCLibcHeapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} static const char* name() { - return "System.glibc_trim_heap"; + return "System.trim_native_heap"; } static const char* description() { - return "Attempts to free up memory by trimming the glibc C-heap."; + return "Attempts to free up memory by trimming the C-heap."; } static const char* impact() { return "Low"; diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java index c79b35a12be6e..2688c8e8fe7e5 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/TrimLibcHeapTest.java @@ -40,7 +40,7 @@ */ public class TrimLibcHeapTest { public void run(CommandExecutor executor) { - OutputAnalyzer output = executor.execute("System.glibc_trim_heap"); + OutputAnalyzer output = executor.execute("System.trim_native_heap"); output.reportDiagnosticSummary(); output.shouldMatch("(Done|Not available)"); // Not available could happen on Linux + non-glibc (eg. muslc) if (output.firstMatch("Done") != null) {