RFR: Generation resizing [v3]

Y. Srinivas Ramakrishna ysr at openjdk.org
Fri Dec 9 01:11:16 UTC 2022


On Tue, 6 Dec 2022 17:26:08 GMT, William Kemper <wkemper at openjdk.org> wrote:

>> These changes have the generational mode track the minimum mutator utilization (percentage of process time used by mutators). When it falls below a configuration percentage (GCTimeRatio), a heuristic will transfer memory capacity to whatever generation has been using more CPU time. The assumption here is that by increasing capacity, we will decrease the collection frequency and improve the MMU.
>
> William Kemper has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Remove vestigial lock, do not enroll periodic task while holding threads_lock

src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 980:

> 978: }
> 979: 
> 980: void ShenandoahGeneration::increase_capacity(size_t increment) {

is there some sanity check done on this elsewhere to make sure the increase/decrease make sense? Perhaps I'll see it in the caller(s) when I get to it.

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

> 1093: }
> 1094: 
> 1095: bool ShenandoahHeap::adjust_generation_sizes() {

Is this method idempotent? I guess it depends on the method of the same name in the MMU Tracker. I guess my question will be answered when I get to it.

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 37:

> 35:  * This class is responsible for tracking and adjusting the minimum mutator
> 36:  * utilization (MMU). MMU is defined as the percentage of CPU time available
> 37:  * to mutator threads over an arbitrary, fixed interval of time. MMU is measured

Where do we specify the fixed interval used as the basis for the MMU?

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 38:

> 36:  * utilization (MMU). MMU is defined as the percentage of CPU time available
> 37:  * to mutator threads over an arbitrary, fixed interval of time. MMU is measured
> 38:  * by summing all of the time given to the GC threads and comparing this too

too -> to

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 44:

> 42:  * The time spent by GC threads is attributed to the young or old generation.
> 43:  * The time given to the controller and regulator threads is attributed to the
> 44:  * global generation. At the end of every collection, the average MMU is inspected.

average over ...? Average MMU over the most recently ended collection cycle? Or over the cumulative history of the run? Or over all of the collection cycles since the last adjustment of generation sizes? etc.

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 61:

> 59:   TruncatedSeq _mmu_average;
> 60: 
> 61:   bool transfer_capacity(ShenandoahGeneration* from, ShenandoahGeneration* to);

Nit:  Shouldn't the adjustment be in a sizer object rather than in a tracker object? May be we think of this class as an MmuBasedGenerationSizeController which both tracks MMU and controls the size of the generations.

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 90:

> 88:   // allocators by taking the heap lock). The amount of capacity to move
> 89:   // from one generation to another is controlled by YoungGenerationSizeIncrement
> 90:   // and defaults to 20% of the heap. The minimum and maximum sizes of the

Is the transfer delta always 20%? Wouldn't that cause oscillations about an equilibrium point at steady load? But I should read on to see how this works.

src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp line 93:

> 91:   // young generation are controlled by ShenandoahMinYoungPercentage and
> 92:   // ShenandoahMaxYoungPercentage, respectively. The method returns true
> 93:   // when and adjustment is made, false otherwise.

and -> an

src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp line 95:

> 93: 
> 94: void ShenandoahYoungGeneration::add_collection_time(double time_seconds) {
> 95:   if (_old_gen_task_queues != NULL) {

This seems a bit subtle. Isn't there a better/official status flag to check, or a default second parm to leverage from caller?

src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp line 59:

> 57:   virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override;
> 58: 
> 59:   virtual void add_collection_time(double time_seconds) override;

A 1-line documentation comment/spec for the method would be nice here.

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

PR: https://git.openjdk.org/shenandoah/pull/177


More information about the shenandoah-dev mailing list