8307374: Add a JFR event for tracking RSS
Reviewed-by: stuefe, rcastanedalo
This commit is contained in:
parent
1de40f360f
commit
5722903d53
@ -3002,3 +3002,9 @@ bool os::supports_map_sync() {
|
||||
}
|
||||
|
||||
void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
void os::jfr_report_memory_info() {}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
@ -69,6 +69,9 @@
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#endif
|
||||
|
||||
// put OS-includes here
|
||||
# include <dlfcn.h>
|
||||
@ -101,6 +104,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/task_info.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
@ -2453,3 +2457,31 @@ bool os::start_debugging(char *buf, int buflen) {
|
||||
}
|
||||
|
||||
void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
void os::jfr_report_memory_info() {
|
||||
#ifdef __APPLE__
|
||||
mach_task_basic_info info;
|
||||
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
|
||||
|
||||
kern_return_t ret = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count);
|
||||
if (ret == KERN_SUCCESS) {
|
||||
// Send the RSS JFR event
|
||||
EventResidentSetSize event;
|
||||
event.set_size(info.resident_size);
|
||||
event.set_peak(info.resident_size_max);
|
||||
event.commit();
|
||||
} else {
|
||||
// Log a warning
|
||||
static bool first_warning = true;
|
||||
if (first_warning) {
|
||||
log_warning(jfr)("Error fetching RSS values: task_info failed");
|
||||
first_warning = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
@ -77,6 +77,9 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#endif
|
||||
|
||||
// put OS-includes here
|
||||
# include <sys/types.h>
|
||||
@ -2470,6 +2473,28 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
print_sys_devices_cpu_info(st);
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
void os::jfr_report_memory_info() {
|
||||
os::Linux::meminfo_t info;
|
||||
if (os::Linux::query_process_memory_info(&info)) {
|
||||
// Send the RSS JFR event
|
||||
EventResidentSetSize event;
|
||||
event.set_size(info.vmrss * K);
|
||||
event.set_peak(info.vmhwm * K);
|
||||
event.commit();
|
||||
} else {
|
||||
// Log a warning
|
||||
static bool first_warning = true;
|
||||
if (first_warning) {
|
||||
log_warning(jfr)("Error fetching RSS values: query_process_memory_info failed");
|
||||
first_warning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
#if defined(AMD64) || defined(IA32) || defined(X32)
|
||||
const char* search_string = "model name";
|
||||
#elif defined(M68K)
|
||||
|
@ -78,6 +78,9 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
#include "windbghelp.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#include <crtdbg.h>
|
||||
@ -6022,6 +6025,33 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
void os::jfr_report_memory_info() {
|
||||
PROCESS_MEMORY_COUNTERS_EX pmex;
|
||||
ZeroMemory(&pmex, sizeof(PROCESS_MEMORY_COUNTERS_EX));
|
||||
pmex.cb = sizeof(pmex);
|
||||
|
||||
BOOL ret = GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmex, sizeof(pmex));
|
||||
if (ret != 0) {
|
||||
// Send the RSS JFR event
|
||||
EventResidentSetSize event;
|
||||
event.set_size(pmex.WorkingSetSize);
|
||||
event.set_peak(pmex.PeakWorkingSetSize);
|
||||
event.commit();
|
||||
} else {
|
||||
// Log a warning
|
||||
static bool first_warning = true;
|
||||
if (first_warning) {
|
||||
log_warning(jfr)("Error fetching RSS values: GetProcessMemoryInfo failed");
|
||||
first_warning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
|
||||
// File conventions
|
||||
const char* os::file_separator() { return "\\"; }
|
||||
const char* os::line_separator() { return "\r\n"; }
|
||||
|
@ -73,6 +73,11 @@
|
||||
<Field type="string" name="name" label="Name" />
|
||||
</Event>
|
||||
|
||||
<Event name="ResidentSetSize" category="Java Virtual Machine, Memory" label="Resident Set Size" description="Resident set size of the process" thread="false" period="everyChunk">
|
||||
<Field type="ulong" contentType="bytes" name="size" label="Resident Set Size" description="Resident set size of the process" />
|
||||
<Field type="ulong" contentType="bytes" name="peak" label="Resident Set Size Peak Value" description="Resident set size peak value of the process" />
|
||||
</Event>
|
||||
|
||||
<!-- Ordinary and experimental events !-->
|
||||
|
||||
<Event name="ThreadStart" category="Java Application" label="Java Thread Start" thread="true" startTime="false" stackTrace="true">
|
||||
|
@ -95,6 +95,10 @@ PeriodicType JfrPeriodicEventSet::type(void) {
|
||||
return _type;
|
||||
}
|
||||
|
||||
TRACE_REQUEST_FUNC(ResidentSetSize) {
|
||||
os::jfr_report_memory_info();
|
||||
}
|
||||
|
||||
TRACE_REQUEST_FUNC(JVMInformation) {
|
||||
ResourceMark rm;
|
||||
EventJVMInformation event;
|
||||
|
@ -791,6 +791,9 @@ class os: AllStatic {
|
||||
static size_t lasterror(char *buf, size_t len);
|
||||
static int get_last_error();
|
||||
|
||||
// Send JFR memory info event
|
||||
static void jfr_report_memory_info() NOT_JFR_RETURN();
|
||||
|
||||
// Replacement for strerror().
|
||||
// Will return the english description of the error (e.g. "File not found", as
|
||||
// suggested in the POSIX standard.
|
||||
|
@ -7,6 +7,11 @@
|
||||
|
||||
<configuration version="2.0" label="Continuous" description="Low overhead configuration safe for continuous use in production environments, typically less than 1 % overhead." provider="Oracle">
|
||||
|
||||
<event name="jdk.ResidentSetSize">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="period">1000 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ThreadAllocationStatistics">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
|
@ -7,6 +7,11 @@
|
||||
|
||||
<configuration version="2.0" label="Profiling" description="Low overhead configuration for profiling, typically around 2 % overhead." provider="Oracle">
|
||||
|
||||
<event name="jdk.ResidentSetSize">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="period">1000 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ThreadAllocationStatistics">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
|
95
test/jdk/jdk/jfr/event/runtime/TestResidentSetSizeEvent.java
Normal file
95
test/jdk/jdk/jfr/event/runtime/TestResidentSetSizeEvent.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2023, 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.
|
||||
*/
|
||||
|
||||
package jdk.jfr.event.runtime;
|
||||
|
||||
import static jdk.test.lib.Asserts.assertGreaterThan;
|
||||
import static jdk.test.lib.Asserts.assertLessThanOrEqual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.test.lib.jfr.EventNames;
|
||||
import jdk.test.lib.jfr.Events;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib
|
||||
* @modules jdk.jfr
|
||||
* jdk.management
|
||||
* @run main/othervm -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestResidentSetSizeEvent true
|
||||
*/
|
||||
public class TestResidentSetSizeEvent {
|
||||
private final static String ResidentSetSizeEvent = EventNames.ResidentSetSize;
|
||||
|
||||
private final static int Period = 1000;
|
||||
private final static int K = 1024;
|
||||
|
||||
private static ArrayList<byte[]> data = new ArrayList<byte[]>();
|
||||
|
||||
private static void generateHeapContents() {
|
||||
for (int i = 0 ; i < 64; i++) {
|
||||
for (int j = 0; j < K; j++) {
|
||||
data.add(new byte[K]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateEvents(Recording recording) throws Exception {
|
||||
recording.enable(ResidentSetSizeEvent).with("period", "everyChunk");
|
||||
|
||||
recording.start();
|
||||
|
||||
// Generate data to force heap to grow.
|
||||
generateHeapContents();
|
||||
|
||||
recording.stop();
|
||||
}
|
||||
|
||||
private static void verifyExpectedEventTypes(List<RecordedEvent> events) throws Exception {
|
||||
List<RecordedEvent> filteredEvents = events.stream().filter(e -> e.getEventType().getName().equals(ResidentSetSizeEvent)).toList();
|
||||
|
||||
assertGreaterThan(filteredEvents.size(), 0, "Should exist events of type: " + ResidentSetSizeEvent);
|
||||
|
||||
for (RecordedEvent event : filteredEvents) {
|
||||
long size = event.getLong("size");
|
||||
long peak = event.getLong("peak");
|
||||
assertGreaterThan(size, 0L, "Should be non-zero");
|
||||
assertGreaterThan(peak, 0L, "Should be non-zero");
|
||||
assertLessThanOrEqual(size, peak, "The size should be less than or equal to peak");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (Recording recording = new Recording()) {
|
||||
generateEvents(recording);
|
||||
|
||||
var events = Events.fromRecording(recording);
|
||||
verifyExpectedEventTypes(events);
|
||||
}
|
||||
}
|
||||
}
|
@ -186,6 +186,7 @@ public class EventNames {
|
||||
public static final String PhysicalMemory = PREFIX + "PhysicalMemory";
|
||||
public static final String NetworkUtilization = PREFIX + "NetworkUtilization";
|
||||
public static final String ProcessStart = PREFIX + "ProcessStart";
|
||||
public static final String ResidentSetSize = PREFIX + "ResidentSetSize";
|
||||
|
||||
// JDK
|
||||
public static final String FileForce = PREFIX + "FileForce";
|
||||
|
Loading…
x
Reference in New Issue
Block a user