RFR: 8312116: GenShen: make instantaneous allocation rate triggers more timely [v4]

William Kemper wkemper at openjdk.org
Thu Jan 8 22:56:32 UTC 2026


On Wed, 7 Jan 2026 20:56:51 GMT, Kelvin Nilsen <kdnilsen at openjdk.org> wrote:

>> After studying large numbers of GC logs with degenerated cycles that have resulted from "late" triggers, we propose the following general improvements:
>> 
>> 1. Track trends in GC times rather than always using the average GC time plus standard deviation.  In many situations, GC times trend upward due to, for example, increasing amounts of live data that must be marked as a workload builds up its working set of memory.
>> 2. Sample allocation rates more frequently than once every 100 ms.
>> 3. Track trends in allocation rates.  In some situations, the allocation rate trends upwards due to, for example, the start of a new phase of execution or a spike in client workload.
>> 4. When we detect acceleration of allocation rate, predict consumption of memory based on accelerated allocation rates rather than assuming constant allocation rate.
>
> Kelvin Nilsen has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 65 commits:
> 
>  - Fix comment
>  - Use PROPERFMT macros
>  - Simplify code flow: reviewer suggestion
>  - Merge remote-tracking branch 'jdk/master' into accelerated-triggers
>  - Remove develop/debug instrumentation
>  - add another override
>  - Change type of command-line args
>  - fix white space
>  - Add override to virtual methods
>  - Fix race between allocation reporting and querying
>  - ... and 55 more: https://git.openjdk.org/jdk/compare/dd20e915...7f3a6d1e

Changes requested by wkemper (Reviewer).

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 134:

> 132:   if (_is_generational) {
> 133:     _regulator_thread = ShenandoahGenerationalHeap::heap()->regulator_thread();
> 134:     size_t young_available = ShenandoahGenerationalHeap::heap()->young_generation()->max_capacity() -

Consider pushing this down into `ShenandoahGenerationalHeuristics`

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 145:

> 143: }
> 144: 
> 145: double ShenandoahAdaptiveHeuristics::get_most_recent_wake_time() const {

This introduces a cyclic dependency between control/regulator threads and the heuristics. Since control/regulator threads already _know_ about heuristics, could we instead have the threads invoke setters on the heuristics to provide these values?

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 192:

> 190: 
> 191: void ShenandoahAdaptiveHeuristics::resume_idle_span() {
> 192:   size_t mutator_available = _free_set->capacity() - _free_set->used();

This is a little confusing to me. Isn't `available` defined as `capacity - used`? Why do we not use `available` here?

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 715:

> 713: 
> 714:   if (ShenandoahHeuristics::should_start_gc()) {
> 715:     // ShenandoahHeuristics::should_start_gc() has accepted trigger, or declined it.

return ShenandoahHeuristics::should_start_gc();

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp line 73:

> 71:   bool is_spiking(double rate, double threshold) const;
> 72: 
> 73:   double interval() const {

Not seeing where these new methods are used.

src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp line 316:

> 314:   if (progress) {
> 315:     heap->notify_gc_progress();
> 316:     heap->shenandoah_policy()->record_success_degenerated(_generation->is_young(), _abbreviated);

On line 313 above here, we call `policy->record_degenerated` which does everything (and more) that `record_success_degenerated` does. Calling both of them here will increment the various counters twice and is probably not what we want. I think after https://github.com/openjdk/jdk/pull/28834, we shouldn't need `record_success_degenerated` for `ShenandoahCollectorPolicy` at all.

src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp line 493:

> 491:   ShenandoahCodeRoots::initialize();
> 492: 
> 493:   // Initialization of controller markes use of varaibles esstablished by initialize_heuristics.

Suggestion:

  // Initialization of controller makes use of variables established by initialize_heuristics.

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

PR Review: https://git.openjdk.org/jdk/pull/29039#pullrequestreview-3641395012
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2673966020
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2673969760
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2674066185
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2674110503
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2674122093
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2674156144
PR Review Comment: https://git.openjdk.org/jdk/pull/29039#discussion_r2674168920


More information about the hotspot-gc-dev mailing list