JDK-8349978 : G1: Reconsider G1 GCTimeRatio boosting during heap expansion for small heaps
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2025-02-13
  • Updated: 2025-02-17
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.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Currently G1 boosts heap expansion, artificially reducing the target pause time threshold (i.e. the cpu time the collector is allowed to use), if the heap's current capacity is <= 1/2 of maximum capacity.

This heuristic is (ultimately) an artifact of the original implementation where expansion at low heap sizes doubled the heap size (sans some minor other conditions) to keep throughput (benchmark scores) almost the same after JDK-8060697.

(Aggressively scaling the heap up decreases the number of GCs to meet the GCTimeRatio, and since it then often overshoots, makes young gen potentially very large, combined with general reluctance on decreasing the heap, reducing GCs as well)

This has several drawbacks though:
* inflates the heap usage; G1 is often running at actual cpu usage far below what would be allowed by GCTimeRatio.
* particularly the case where one wants to keep average memory consumption low but allow headroom for memory usage spikes (to not OOME), is underserved and/or very hard to achieve.
* is surprising for users of GCTimeRatio that there are cases when it is not observed at all

In combination with other suggestions like JDK-8247843,  	JDK-8238687, JDK-8236073 and others it may be possible to get rid of this heuristic.
Comments
If you look at the relevant changes for JDK-8060697: size_t G1CollectorPolicy::expansion_amount() { double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0; double last_gc_overhead = _last_pause_time_ratio * 100.0; double threshold = _gc_overhead_perc; - if (recent_gc_overhead > threshold) { - // We will double the existing space, or take - // G1ExpandByPercentOfAvailable % of the available expansion - // space, whichever is smaller, bounded below by a minimum - // expansion (unless that's all that's left.) - const size_t min_expand_bytes = 1*M; size_t expand_bytes = 0; + // If the heap is at less than half its maximum size, scale the threshold down, + // to a limit of 1. Thus the smaller the heap is, the more likely it is to expand, + // though the scaling code will likely keep the increase small. + if (_g1->capacity() <= _g1->max_capacity() / 2) { + threshold *= (double)_g1->capacity() / (double)(_g1->max_capacity() / 2); + threshold = MAX2(threshold, 1.0); + } That removed comment shows that previous very aggressive heap scaling behavior, replaced by this new one based on boosting GCTimeRatio, which at a later point got extracted into a helper method.
13-02-2025