Aligning the Serial collector with ZGC

Thomas Schatzl thomas.schatzl at oracle.com
Wed Oct 2 06:47:52 UTC 2024


Hi,

On 28.09.24 00:55, Kirk Pepperdine wrote:
> Hi Thomas,
> 
> I wanted to respond to all of your comments but I thought better of it 
> given one response deserves it’s own email. The focus is mostly on that 
> one question.
> 
>> >
>> > - Introduce an adaptive size policy that takes into account memory and
>> > CPU pressure along with global memory pressure.
>> >     - Heap should be large enough to minimize GC overhead but not
>> > large enough to trigger OOM.
>>
>> (probably meant "small enough" the second time)
> 
> I actually did mean large but in the context of OOM killer…. But to your 
> point, smaller but avoid OOME is also a concern.
> 
>>
>> >     - Introduce -XX:SerialPressure=[0-100] to support this work.
>>
>> (Fwiw, regards to the other discussion, I agree that if we have a flag 
>> with the same "meaning" across collectors it might be useful to use 
>> the same name).
> 
> I think we have deadly agreement on this one.
> 
>>
>> >     - introduce a smoothing algorythm to avoid excessive small
>> > resizes.
>>
>> One option is to split this further into parts:
>>
>> * list what actions Serial GC could do in reaction to memory pressure 
>> on an abstract level, and which make sense; from that see what 
>> functionality is needed.
> 
> I built a chart some time ago and this is an expanded version of it.
> 
[...]
> 
> Some of my thoughts used to construct the table.
> 
[...]
> All of the resizing decisions need to be moderated by the availability 
> of (global) memory. If global memory is scarce, then the decision should 
> favour releasing (uncommitting) memory. This may come at the expense of 
> higher GC overhead. Resizing to smaller pool sizes is not without risk 
> and in the case of young, both high global memory pressure and high 
> allocation pressure add to the risk.
> 

Thank you for sharing your detailed thoughts.

> 
> 
>>
>> * provide functionality that tries to keep some kind of GC/mutator 
>> time ratio; I would start with looking at G1 does because Serial GC's 
>> behaviour is probably closer to G1 than ZGC, but ymmv.
>> (Obviously improvements are welcome :))
> 
> I would agree.

Here's some old code for implementing 
https://bugs.openjdk.org/browse/JDK-8238687: Uncommit at every GC that 
improves a bit on the current G1 policy which implements both signalling 
for under/over-cpu usage ratio, which is maybe better (documented) than 
the existing code.

https://github.com/openjdk/jdk/compare/master...tschatzl:jdk:investigate-memory-uncommit-every-gc-only

[...]

>> > - Introduce manageable flag SoftMaxHeapSize to define a target heap
>> > size nd set the default max heap size to 100% of available.
>>
>> I am a bit torn about SoftMaxHeapSize in Serial GC. What do you 
>> envision that Serial GC would do when the SoftMaxHeapSize has been 
>> reached, and what if old gen occupancy permanently stays above that value?
> 
> At the moment, SoftMaxHeapSize is an implementation in Z. I’d first like 
> to pull a (rough) spec out of the implementation and then try to answer 
> your question. It’s currently not clear to me how this should work with 
> any collector.
>>
>> The usefulness of SoftMaxHeapSize kind of relies on having a minimally 
>> invasive old gen collection that tries to get old gen usage back below 
>> that value.
> 
> Well, the LDS is what it is and running a speculative collection would 
> likely clean up (prematurely) promoted transients… but that’s about it. 
> Whereas it would clean both transients and floating garbage for the 
> concurrent collectors. I’m not at fan of speculative collections given 
> all of the time I’ve spent getting rid of them :-) IMO, a DGC triggered 
> full collections was rarely necessary (all overhead with very little 
> return). This also applied to the G1 patch that speculatively ran to 
> counter to-space overflows and it also applied to running a young gen 
> prior to remark with CMS collector. Long story sort, loads of extra 
> overhead with very little to no payback.

SoftMaxHeapSize is a bit different as it is non-speculative but 
supposedly based on the users intent.

>> Serial GC has no "minimally invasive" way to collect old generation. 
>> It is either Full GC or nothing. This is the only option for Serial, 
>> but always doing Full collections after reaching that threshold seems 
>> very heavy handed, expensive and undesirable to me (ymmv).
>>
>> That reaction would follow the spirit of the flag though.
>>
>> Maybe at the small heaps Serial GC targets, this makes sense, and full 
>> gc is not that costly anyway.
> 
> Yeah, for small heap this shouldn’t be a big deal. But this is one of 
> the reasons why I believe we should treat young and old separately. We 
> can cheaply and safely return memory from young gen and leave the sizing 
> of tenured to when a full is really needed. I grant you that this may 
> not be very timely but I’m not sure that we need this to happen on 
> demand… I think we can wait for natural cycles to take their course. 
> But, maybe I’m wrong on this point. We plan to experiment with this.

Please do and report back.

>>
>> It might be useful to enumerate what actions could be performed on 
>> global pressure.
> 
> That’s in the table…
> 
>>
>> > - Add in the ability to uncommit memory (to reduce global memory
>> > pressure).
>> >
>>
>> The following imo outlines a compdoneletely separate idea, and should 
>> be discussed separately:
>>
>> >
>> > While working through the details of this work I noted that there
>> > appear  to opportunities to offer new defaults for other settings. For
>> > example, [...]
>>
>> That seems to be some more elaborate way of finding "optimal" 
>> generation size for a given heap size (which may follow from what the 
>> gc/mutator time ratio algorithm gives you).
> 
> I’m trying to apply my years of experience tuning 100s of collectors 
> across 100s of applications.
> 

Very much appreciated.

Hth,
   Thomas



More information about the hotspot-gc-dev mailing list