RFR: 8365306: Provide OS Process Size and Libc statistic metrics to JFR
Erik Gahlin
egahlin at openjdk.org
Tue Aug 26 13:05:42 UTC 2025
On Wed, 13 Aug 2025 09:42:57 GMT, Thomas Stuefe <stuefe at openjdk.org> wrote:
> This provides the following new metrics:
> - `ProcessSize` event (new, periodic)
> - vsize (for analyzing address-space fragmentation issues)
> - RSS including subtypes (subtypes are useful for excluding atypical issues, e.g. kernel problems that cause large file buffer bloat)
> - peak RSS
> - process swap (if we swap we cannot trust the RSS values, plus it indicates bad sizing)
> - pte size (to quickly see if we run with a super-large working set but an unsuitably small page size)
> - `LibcStatistics` (new, periodic)
> - outstanding malloc size (important counterpoint to whatever NMT tries to tell me, which alone is often misleading)
> - retained malloc size (super-important for the same reason)
> - number of libc trims the hotspot executed (needed to gauge the usefulness of the retain counter, and to see if a customer employs native heap auto trimming (`-XX:TrimNativeHeapInterval`)
> - `NativeHeapTrim` (new, event-driven) (for both manual and automatic trims)
> - RSS before and RSS after
> - RSS recovered by this trim
> - whether it was an automatic or manual trim
> - duration
> - `JavaThreadStatistic`
> - os thread counter (new field) (useful to understand the behavior of third-party code in our process if threads are created that bypass the JVM. E.g. some custom launchers do that.)
> - nonJava thread counter (new field) (needed to interprete the os thread counter)
>
> Notes:
> - we already have `ResidentSetSize` event, and the new `ProcessSize` event is a superset of that. I don't know how these cases are handled. I'd prefer to throw the old event out, but JMC has a hard-coded chart for RSS, so I kept it in unless someone tells me to remove it.
>
> - Obviously, the libc events are very platform-specific. Still, I argue that these metrics are highly useful. We want people to use JFR and JMC; people include developers that are dealing with performance problems that require platform-specific knowledge to understand. See my comment in the JBS issue.
>
> I provided implementations, as far as possible, to Linux, MacOS and Windows.
>
> Testing:
> - ran the new tests manually and as part of GHAs
Events can be viewed as tables in a relational database. Duplicating information or designing tables based on the user interface is not a good idea. Correlating or grouping data from different events is not a new problem. The way we have solved it in the past is by using an explicit ID, similar to a foreign key (gcId, compilerId, safepointId etc), or by using the same timestamp (ActiveSetting, NativeMemory* etc.). In this case, I think a timestamp makes more sense. Tools can place the value on a timeline and have memory on the y-axis.
An alternative design is to do something similar to the NativeMemoryUsage event. That is, to split the data per type
<Event name="ProcessMemoryUsage">
<Field type="MemoryType" name="type" label="Type" />
<Field type="ulong" contentType="bytes" name="amount" label="Amount"/>
</Event>
and then emit what is supported on a specific platform and have all those event with the same timestamp.
I'm not sure which of the following memory types make sense to include, there is also a maintenance aspect, or if it the list is correct or complete, but the data would be normalized, even if it differs depending on the platform.
Memory Type Linux macOS Windows Description
-------------------------- ------ -------- --------- ----------------------------------------------------------'
Resident Set Size Yes Yes - Resident memory currently in physical RAM
Private Bytes - - Yes Privately allocated memory
Shared Memory Yes Yes Yes Memory shared among processes
Virtual Memory Size Yes Yes Yes Total reserved address space
Commit Charge - - Yes Promised/guaranteed memory for process
Mapped File Memory Yes Yes Yes Memory mapped from files
Page Table Size Yes - - Memory used for page tables
Swap / Swapped Yes Yes Yes Memory swapped out to disk
Wired Memory - Yes - Locked memory that can't be paged out
Compressed Memory - Yes - Memory compressed by the system
Paged Pool - - Yes Pool for pageable kernel allocations
Non-paged Pool - - Yes Pool for non-pageable kernel allocations
Working Set - - Yes Memory pages currently in RAM for the process
Stack Yes Yes Yes Memory used by call stacks
Heap / Malloc Yes Yes Yes Dynamically allocated memory (heap)
Image Yes Yes - Memory used for executables and loaded libraries
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26756#issuecomment-3224085095
More information about the hotspot-dev
mailing list