Skip to content

Commit 5722903

Browse files
committed
8307374: Add a JFR event for tracking RSS
Reviewed-by: stuefe, rcastanedalo
1 parent 1de40f3 commit 5722903

File tree

11 files changed

+211
-0
lines changed

11 files changed

+211
-0
lines changed

src/hotspot/os/aix/os_aix.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,3 +3002,9 @@ bool os::supports_map_sync() {
30023002
}
30033003

30043004
void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
3005+
3006+
#if INCLUDE_JFR
3007+
3008+
void os::jfr_report_memory_info() {}
3009+
3010+
#endif // INCLUDE_JFR

src/hotspot/os/bsd/os_bsd.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
#include "utilities/events.hpp"
7070
#include "utilities/growableArray.hpp"
7171
#include "utilities/vmError.hpp"
72+
#if INCLUDE_JFR
73+
#include "jfr/jfrEvents.hpp"
74+
#endif
7275

7376
// put OS-includes here
7477
# include <dlfcn.h>
@@ -101,6 +104,7 @@
101104
#endif
102105

103106
#ifdef __APPLE__
107+
#include <mach/task_info.h>
104108
#include <mach-o/dyld.h>
105109
#endif
106110

@@ -2453,3 +2457,31 @@ bool os::start_debugging(char *buf, int buflen) {
24532457
}
24542458

24552459
void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
2460+
2461+
#if INCLUDE_JFR
2462+
2463+
void os::jfr_report_memory_info() {
2464+
#ifdef __APPLE__
2465+
mach_task_basic_info info;
2466+
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
2467+
2468+
kern_return_t ret = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count);
2469+
if (ret == KERN_SUCCESS) {
2470+
// Send the RSS JFR event
2471+
EventResidentSetSize event;
2472+
event.set_size(info.resident_size);
2473+
event.set_peak(info.resident_size_max);
2474+
event.commit();
2475+
} else {
2476+
// Log a warning
2477+
static bool first_warning = true;
2478+
if (first_warning) {
2479+
log_warning(jfr)("Error fetching RSS values: task_info failed");
2480+
first_warning = false;
2481+
}
2482+
}
2483+
2484+
#endif // __APPLE__
2485+
}
2486+
2487+
#endif // INCLUDE_JFR

src/hotspot/os/linux/os_linux.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
#include "utilities/macros.hpp"
7878
#include "utilities/powerOfTwo.hpp"
7979
#include "utilities/vmError.hpp"
80+
#if INCLUDE_JFR
81+
#include "jfr/jfrEvents.hpp"
82+
#endif
8083

8184
// put OS-includes here
8285
# include <sys/types.h>
@@ -2470,6 +2473,28 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
24702473
print_sys_devices_cpu_info(st);
24712474
}
24722475

2476+
#if INCLUDE_JFR
2477+
2478+
void os::jfr_report_memory_info() {
2479+
os::Linux::meminfo_t info;
2480+
if (os::Linux::query_process_memory_info(&info)) {
2481+
// Send the RSS JFR event
2482+
EventResidentSetSize event;
2483+
event.set_size(info.vmrss * K);
2484+
event.set_peak(info.vmhwm * K);
2485+
event.commit();
2486+
} else {
2487+
// Log a warning
2488+
static bool first_warning = true;
2489+
if (first_warning) {
2490+
log_warning(jfr)("Error fetching RSS values: query_process_memory_info failed");
2491+
first_warning = false;
2492+
}
2493+
}
2494+
}
2495+
2496+
#endif // INCLUDE_JFR
2497+
24732498
#if defined(AMD64) || defined(IA32) || defined(X32)
24742499
const char* search_string = "model name";
24752500
#elif defined(M68K)

src/hotspot/os/windows/os_windows.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@
7878
#include "utilities/macros.hpp"
7979
#include "utilities/vmError.hpp"
8080
#include "windbghelp.hpp"
81+
#if INCLUDE_JFR
82+
#include "jfr/jfrEvents.hpp"
83+
#endif
8184

8285
#ifdef _DEBUG
8386
#include <crtdbg.h>
@@ -6022,6 +6025,33 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {
60226025
}
60236026
}
60246027

6028+
#if INCLUDE_JFR
6029+
6030+
void os::jfr_report_memory_info() {
6031+
PROCESS_MEMORY_COUNTERS_EX pmex;
6032+
ZeroMemory(&pmex, sizeof(PROCESS_MEMORY_COUNTERS_EX));
6033+
pmex.cb = sizeof(pmex);
6034+
6035+
BOOL ret = GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmex, sizeof(pmex));
6036+
if (ret != 0) {
6037+
// Send the RSS JFR event
6038+
EventResidentSetSize event;
6039+
event.set_size(pmex.WorkingSetSize);
6040+
event.set_peak(pmex.PeakWorkingSetSize);
6041+
event.commit();
6042+
} else {
6043+
// Log a warning
6044+
static bool first_warning = true;
6045+
if (first_warning) {
6046+
log_warning(jfr)("Error fetching RSS values: GetProcessMemoryInfo failed");
6047+
first_warning = false;
6048+
}
6049+
}
6050+
}
6051+
6052+
#endif // INCLUDE_JFR
6053+
6054+
60256055
// File conventions
60266056
const char* os::file_separator() { return "\\"; }
60276057
const char* os::line_separator() { return "\r\n"; }

src/hotspot/share/jfr/metadata/metadata.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@
7373
<Field type="string" name="name" label="Name" />
7474
</Event>
7575

76+
<Event name="ResidentSetSize" category="Java Virtual Machine, Memory" label="Resident Set Size" description="Resident set size of the process" thread="false" period="everyChunk">
77+
<Field type="ulong" contentType="bytes" name="size" label="Resident Set Size" description="Resident set size of the process" />
78+
<Field type="ulong" contentType="bytes" name="peak" label="Resident Set Size Peak Value" description="Resident set size peak value of the process" />
79+
</Event>
80+
7681
<!-- Ordinary and experimental events !-->
7782

7883
<Event name="ThreadStart" category="Java Application" label="Java Thread Start" thread="true" startTime="false" stackTrace="true">

src/hotspot/share/jfr/periodic/jfrPeriodic.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ PeriodicType JfrPeriodicEventSet::type(void) {
9595
return _type;
9696
}
9797

98+
TRACE_REQUEST_FUNC(ResidentSetSize) {
99+
os::jfr_report_memory_info();
100+
}
101+
98102
TRACE_REQUEST_FUNC(JVMInformation) {
99103
ResourceMark rm;
100104
EventJVMInformation event;

src/hotspot/share/runtime/os.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,9 @@ class os: AllStatic {
791791
static size_t lasterror(char *buf, size_t len);
792792
static int get_last_error();
793793

794+
// Send JFR memory info event
795+
static void jfr_report_memory_info() NOT_JFR_RETURN();
796+
794797
// Replacement for strerror().
795798
// Will return the english description of the error (e.g. "File not found", as
796799
// suggested in the POSIX standard.

src/jdk.jfr/share/conf/jfr/default.jfc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
<configuration version="2.0" label="Continuous" description="Low overhead configuration safe for continuous use in production environments, typically less than 1 % overhead." provider="Oracle">
99

10+
<event name="jdk.ResidentSetSize">
11+
<setting name="enabled">true</setting>
12+
<setting name="period">1000 ms</setting>
13+
</event>
14+
1015
<event name="jdk.ThreadAllocationStatistics">
1116
<setting name="enabled">true</setting>
1217
<setting name="period">everyChunk</setting>

src/jdk.jfr/share/conf/jfr/profile.jfc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
<configuration version="2.0" label="Profiling" description="Low overhead configuration for profiling, typically around 2 % overhead." provider="Oracle">
99

10+
<event name="jdk.ResidentSetSize">
11+
<setting name="enabled">true</setting>
12+
<setting name="period">1000 ms</setting>
13+
</event>
14+
1015
<event name="jdk.ThreadAllocationStatistics">
1116
<setting name="enabled">true</setting>
1217
<setting name="period">everyChunk</setting>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package jdk.jfr.event.runtime;
25+
26+
import static jdk.test.lib.Asserts.assertGreaterThan;
27+
import static jdk.test.lib.Asserts.assertLessThanOrEqual;
28+
29+
import java.util.ArrayList;
30+
import java.util.List;
31+
32+
import jdk.jfr.Recording;
33+
import jdk.jfr.consumer.RecordedEvent;
34+
import jdk.test.lib.jfr.EventNames;
35+
import jdk.test.lib.jfr.Events;
36+
37+
/**
38+
* @test
39+
* @key jfr
40+
* @requires vm.hasJFR
41+
* @library /test/lib
42+
* @modules jdk.jfr
43+
* jdk.management
44+
* @run main/othervm -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestResidentSetSizeEvent true
45+
*/
46+
public class TestResidentSetSizeEvent {
47+
private final static String ResidentSetSizeEvent = EventNames.ResidentSetSize;
48+
49+
private final static int Period = 1000;
50+
private final static int K = 1024;
51+
52+
private static ArrayList<byte[]> data = new ArrayList<byte[]>();
53+
54+
private static void generateHeapContents() {
55+
for (int i = 0 ; i < 64; i++) {
56+
for (int j = 0; j < K; j++) {
57+
data.add(new byte[K]);
58+
}
59+
}
60+
}
61+
62+
private static void generateEvents(Recording recording) throws Exception {
63+
recording.enable(ResidentSetSizeEvent).with("period", "everyChunk");
64+
65+
recording.start();
66+
67+
// Generate data to force heap to grow.
68+
generateHeapContents();
69+
70+
recording.stop();
71+
}
72+
73+
private static void verifyExpectedEventTypes(List<RecordedEvent> events) throws Exception {
74+
List<RecordedEvent> filteredEvents = events.stream().filter(e -> e.getEventType().getName().equals(ResidentSetSizeEvent)).toList();
75+
76+
assertGreaterThan(filteredEvents.size(), 0, "Should exist events of type: " + ResidentSetSizeEvent);
77+
78+
for (RecordedEvent event : filteredEvents) {
79+
long size = event.getLong("size");
80+
long peak = event.getLong("peak");
81+
assertGreaterThan(size, 0L, "Should be non-zero");
82+
assertGreaterThan(peak, 0L, "Should be non-zero");
83+
assertLessThanOrEqual(size, peak, "The size should be less than or equal to peak");
84+
}
85+
}
86+
87+
public static void main(String[] args) throws Exception {
88+
try (Recording recording = new Recording()) {
89+
generateEvents(recording);
90+
91+
var events = Events.fromRecording(recording);
92+
verifyExpectedEventTypes(events);
93+
}
94+
}
95+
}

test/lib/jdk/test/lib/jfr/EventNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ public class EventNames {
186186
public static final String PhysicalMemory = PREFIX + "PhysicalMemory";
187187
public static final String NetworkUtilization = PREFIX + "NetworkUtilization";
188188
public static final String ProcessStart = PREFIX + "ProcessStart";
189+
public static final String ResidentSetSize = PREFIX + "ResidentSetSize";
189190

190191
// JDK
191192
public static final String FileForce = PREFIX + "FileForce";

0 commit comments

Comments
 (0)