SapMachine 21 #2165: G1 should initiate the next concurrent cycle even before finishing a mixed phase if there are excessive hum. allocations#2166
Conversation
|
Hello @reinrich, this pull request fulfills all formal requirements. |
RealCLanger
left a comment
There was a problem hiding this comment.
Only a formal review, not a technical one. For that, @schmelter-sap or @TheRealMDoerr, please have a look. Thx.
|
Thanks Christoph. I've pushed the requested changes. |
|
Hello @reinrich, this pull request fulfills all formal requirements. |
| "more than that number of cards to be used.") \ | ||
| \ | ||
| /* SapMachine 2026-01-20 */ \ | ||
| product(uintx, G1HumAllocPercentUntilConcurrent, 0, EXPERIMENTAL, \ |
There was a problem hiding this comment.
I think this name is only understandable for G1 nerds ;-)
Would be great if the name could indicate that we start a new concurrent full GC after the threshold has been reached. Maybe G1HumPercentConcFullGCThreshold?
There was a problem hiding this comment.
I would wager that anyone who does not know the Parameter has to read the doc anyways. So stuffing in every related keyword doesn't really help.
Thus I would suggest something more readable like G1HumongousAllocThreshold.
There was a problem hiding this comment.
What about G1MixedGCHumongousAllocThreshold? That name is similar to other options above.
There was a problem hiding this comment.
The Mixed GC is cancelled and a (concurrent) Full GC started, right?
G1HumongousAllocFullGCThreshold would be more comprehensive for me. Can this only happen if a Mixed GC is running or why would you want to have MixedGC in the name?
There was a problem hiding this comment.
The mixed gc phase (sequence of mixed evacuation pauses) is ended prematurely and a new cycle is initiated. Please have a look at G1MixedGCCountTarget which is related. It's that phase of mixed gcs where G1 wants to make use of the liveness info computed by the marking to evacuate old regions with a lot of unreachable objects. G1 won't start new marking before it is done with the mixed gcs. I thought that G1MixedGCHumongousAllocThreshold matches the existing option and is also descriptive.
There was a problem hiding this comment.
Not the name I'd prefer from a Java developer's perspective, but ok. It's just a name of an experimental option and users can read the documentation which is good IMHO.
schmelter-sap
left a comment
There was a problem hiding this comment.
Some more cosmetic remarks. Looks good otherwise.
src/hotspot/share/gc/g1/g1Policy.cpp
Outdated
| } | ||
|
|
||
| // SapMachine 2026-01-20: force G1 marking in mixed phase in case of excessive hum. allocations | ||
| bool G1Policy::force_concurrent_ending_mixed_phase(bool hum_alloc) { |
There was a problem hiding this comment.
The method name makes it look like it does ending the phase instead of just deciding if it should be stopped.
src/hotspot/share/gc/g1/g1Policy.cpp
Outdated
| (cause == GCCause::_wb_breakpoint)) { | ||
| (cause == GCCause::_wb_breakpoint) || | ||
| // SapMachine 2026-01-20: force G1 marking in mixed phase in case of excessive hum. allocations | ||
| (force_concurrent_ending_mixed_phase(cause == GCCause::_g1_humongous_allocation))) { |
There was a problem hiding this comment.
It seems the hum_alloc boolean argument in the call to force_concurrent_ending_mixed_phase is only needed for this code.
You could use ?: here and remove the argument form the call, since hum_alloc being false just means the method returns false.
There was a problem hiding this comment.
In need_to_start_conc_mark() I wanted to make the call only if called by attempt_allocation_humongous() in order to change the behavior as little as possible. I've changed the callers to make the call only if a hum. alloc. is going on. Is that ok?
src/hotspot/share/gc/g1/g1Policy.cpp
Outdated
| log_debug(gc, ergo)("Initiate concurrent cycle (%s requested concurrent cycle)", | ||
| (cause == GCCause::_wb_breakpoint) ? "run_to breakpoint" : "user"); | ||
| // SapMachine 2026-01-20: force G1 marking in mixed phase in case of excessive hum. allocations | ||
| log_debug(gc, ergo)("Initiate concurrent cycle (%s)", GCCause::to_string(cause)); |
There was a problem hiding this comment.
Wouldn't that change the log output for all kinds of GC causes?
There was a problem hiding this comment.
But it's incorrect anyway. The causes related to the code cache are logged as "user requested". I can revert my change and print s.th. different for cause == GCCause::_g1_humongous_allocation. Shall I?
There was a problem hiding this comment.
Can this disturb anyone who is parsing the logs? Otherwise, the change looks fine to me.
There was a problem hiding this comment.
Could be. I've reverted my change but kept the new output for the new case _g1_humongous_allocation.
|
Thanks for the reviews! Please have a look at the commits where I addressed them. |
|
Hello @reinrich, this pull request fulfills all formal requirements. |
|
Hello @reinrich, this pull request fulfills all formal requirements. |
TheRealMDoerr
left a comment
There was a problem hiding this comment.
I think this is a helpful feature. The implementation LGTM. I've checked that the test fails without the fix and passes with it.
|
Thanks Martin. As mentioned in our daily I've done some further testing with another synthetic gc test that's hopefully a little bit more realistic than the reproducer from 8355972. The test fills the heap with short- and medium-lived and also with permanent objects and then keeps allocating - also humogous objects. I've adapted the test to pause allocations about every 10s except for humongous objects. This triggers stw full gcs. With the enhancement these can be avoided mostly. |
|
Please squash when merging. :) |
This pr introduces a new experimental option
G1HumAllocPercentUntilConcurrentthat controls the G1 enhancement described below. With its default value 0 the enhancement is disabled.A value >0 is interpreted as threshold for humongous allocations given as percentage of the maximum heap size. The threshold limits humongous allocations between mixed evacuation pauses. If reached the current mixed phase is aborted in favor of a new concurrent marking cycle.
Without this enhancement G1 would not initiate concurrent marking in a mixed phase. The problem with this behavior is that the heap can fill up with humongous allocations while G1 waits for the next mixed evacuation pause that will be scheduled only when eden is full. If the heap is full of humongous objects before then a full gc is necessary.
Testing
The reproducer from
doesn't show full gcs if the enhancement is enabled with
-XX:+UnlockExperimentalVMOptions -XX:G1HumAllocPercentUntilConcurrent=30Full command:
The change includes a regression test similar to the reproducer.
A patch with G1HumAllocPercentUntilConcurrent=10 is part of our nightly testing since January 30.
fixes #2165