RFR: 8357445: G1: Time-Based Heap Uncommit During Idle Periods [v7]

Thomas Schatzl tschatzl at openjdk.org
Tue Sep 2 10:09:59 UTC 2025


On Wed, 27 Aug 2025 11:20:36 GMT, Thomas Schatzl <tschatzl at openjdk.org> wrote:

>> Monica Beckwith has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Remove unused static _uncommit_delay member and accessor
>
> src/hotspot/share/gc/g1/g1HeapEvaluationTask.cpp line 54:
> 
>> 52:     log_trace(gc, sizing)("GC active, skipping uncommit evaluation");
>> 53:     return;
>> 54:   }
> 
> This is sketchy. Unless you manually sync, there is no guarantee this is valid. Also since the code is running in a separate thread that might not be stopped during GC, the GC VM operation might just start after this check.

I.e. use `SuspendibleThreadSetJoiner` etc.

> src/hotspot/share/gc/g1/g1HeapRegion.cpp line 253:
> 
>> 251:   _age_index(G1SurvRateGroup::InvalidAgeIndex),
>> 252:   _node_index(G1NUMA::UnknownNodeIndex),
>> 253:   _last_access_timestamp(Ticks::now()), // Initialize timestamp with current time
> 
> Since `G1HeapRegion::initialize()` is called on this region just a bit later, I recommend not wasting the time to call `Ticks::now()` for no gain. Just initialize to a high value(?) and things should work out I think if the code ever comes across such a badly initialized method.

Fwiw, to avoid startup delays (calling `Ticks::now()` on thousands of regions is expensive - I did not test, but it seems reasonable and should be measured), it might be useful to do that initialization lazily (first time the background thread executes).

> src/hotspot/share/gc/g1/g1HeapRegion.hpp line 257:
> 
>> 255:   uint _node_index;
>> 256: 
>> 257:   // Time-based heap sizing: tracks last allocation/access time
> 
> Suggestion:
> 
>   // Time-based heap sizing: tracks last allocation/access time.

The comment is wrong/outdated too, only tracks last freeing (clearing) time. Maybe there is a better name than `_last_access_time` for the member too.

> src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp line 550:
> 
>> 548:       // 1. No more than 25% of inactive regions
>> 549:       // 2. No more than 10% of total committed regions
>> 550:       // 3. No more than max_shrink_bytes worth of regions
> 
> This policy sounds like `Min/MaxHeapFreeRatio` that are known to be not useful. Do not have a better idea right now either. Maybe look at what ZGC did at some point.

I also do not think this mechanism should ever uncommit the free regions reserved for the current young gen (without GC/recalculating the needed young gen) and potentially the survivor/old regions. There does not seem to be a limit here.

Otherwise the next GC (or just continuing work) will be riddled with in-pause commits. Or it will probably do a premature GC, I did not check.

Maybe this change should only madvise these regions as MADV_DONTNEED? (Not sure it does anything though).

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

PR Review Comment: https://git.openjdk.org/jdk/pull/26240#discussion_r2303669369
PR Review Comment: https://git.openjdk.org/jdk/pull/26240#discussion_r2303701876
PR Review Comment: https://git.openjdk.org/jdk/pull/26240#discussion_r2303714473
PR Review Comment: https://git.openjdk.org/jdk/pull/26240#discussion_r2315538730


More information about the hotspot-gc-dev mailing list