JDK-8315149 : Add hsperf counters for CPU time of internal GC threads
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: svc
  • Affected Version: 22
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-08-29
  • Updated: 2025-06-10
  • Resolved: 2023-12-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 22
22 b27Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
There are a number of HsPerf counters that would be useful to track within the JVM to get a better understanding of where CPU time is spent when doing GC.

More specifically, we should introduce counters that track the various CPU time spent in various phases of GC. For example, time spent in:

- Parallel GC: CPU time consumed by parallel GC worker threads, updated after every stop-the-world collection.
- G1 Concurrent Mark (Only available for G1): CPU time consumed by ConcurrentMark thread and concurrent GC worker threads, updated after concurrent root scan, concurrent mark, concurrent cleanup and at the end of a concurrent cycle.
- G1 Concurrent Refine (Only available for G1): CPU time consumed by ConcurrentG1RefineThread threads, updated every time the main worker thread finishes its share of refinement work.
- Concurrent String Dedupliation (Available with +UseStringDeduplication): CPU time consumed by concurrent string deduplication thread, updated every time it finishes processing pending deduplication work.
- VM Thread Time: CPU time consumed by the VMThread, updated after executing every VM_Operation.


For context, the value of these counters was discussed briefly in the context of Container-aware heap sizing: https://mail.openjdk.org/pipermail/hotspot-gc-dev/2022-October/040433.html



--------------------------

Open Questions:

1. Do we want to support these metrics for other GCs, given that the main use case for these counters are for Container-aware heap sizing, which is planned to only be supported for G1GC (for now)? 
- From Google's perspective, I suggest we focus on G1GC, and expand porting these metrics to other GCs if we find it to be useful. This PR has implemented the counters for G1 and ParallelGC.
2. Is there is a better way to report these metrics besides hsperf counters (i.e. `sun.management.HotspotInternal` MBeans, JFR events, or parsing `/proc`)?
- From Google's perspective, the work done with Container-aware heap sizing was done using these hsperf counters, so this would be the smoothest option for us to bring this project upstream without having to re-architect and re-validate our work. Thus, we strongly prefer this implementation.


---------------------

Update: the final hsperf counters added are:

sun.threads.total_gc_cpu_time
sun.threads.cpu_time.gc_parallel_workers
sun.threads.cpu_time.gc_conc_mark
sun.threads.cpu_time.gc_conc_refine
sun.threads.cpu_time.gc_service
sun.threads.cpu_time.vm
sun.threads.cpu_time.conc_dedup
Comments
Changeset: 9e570105 Author: Jonathan Joo <jjoo@openjdk.org> Committer: Man Cao <manc@openjdk.org> Date: 2023-12-05 19:43:25 +0000 URL: https://git.openjdk.org/jdk/commit/9e570105c30a6e462d08931e2010cef9cd5a6031
05-12-2023

Thank you Volker for the additional context! - Adding hsperf counters for JIT compiler threads sounds great. We have used `java.ci.totalTime` (total wall time spent in compilation) as a proxy when we need to check performance for JIT compiler threads. - The PR covers hsperf counters for both G1 and ParallelGC, and String Deduplication thread is no longer specific to G1. I've updated the description to reflect these.
06-09-2023

I think this is really a serviceability feature (hsperf is serviceability) rather than a GC feature so I changed the sub-component to serviceability. You've already implemented this for the VMThread in your PR and once you've got this pushed I'd like to implement this feature for the JIT compiler threads as well.
06-09-2023

See this mail thread for issues with the current `sun.management.HotspotInternal` MBeans approach: https://mail.openjdk.org/pipermail/core-libs-dev/2023-September/111397.html
06-09-2023

Man and I spent a bit more time considering the alternatives, and here are some initial thoughts: The alternatives (MBeans, proc) require knowing the thread names in order to properly parse, which may not necessarily be consistent across versions/GC types. Even if we did confidently know the thread names, it can still be somewhat complicated to get the data we want from these formats. - Google's implementation of Container-aware heap sizing is fully implemented in C++, so MBeans is inconvenient as we would have to interface with Java code. - Looking into the `/proc/` method, it also is not super intuitive as to which value corresponds to GC time, and it might be difficult to reliably identify all PIDs of the relevant GC threads. We believe this implementation is the cleanest way to access the GC CPU data. The patch itself is fairly lightweight, which justifies the benefit we get in terms of ease of parsing. But definitely open to further discussion on this!
30-08-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15082 Date: 2023-07-31 01:50:07 +0000
29-08-2023