Skip to content

SapMachine 21 #2165: G1 should initiate the next concurrent cycle even before finishing a mixed phase if there are excessive hum. allocations#2166

Open
reinrich wants to merge 7 commits intoSAP:sapmachine21from
reinrich:g1_excl_hum_allocs_should_invoke_concurrent
Open

SapMachine 21 #2165: G1 should initiate the next concurrent cycle even before finishing a mixed phase if there are excessive hum. allocations#2166
reinrich wants to merge 7 commits intoSAP:sapmachine21from
reinrich:g1_excl_hum_allocs_should_invoke_concurrent

Conversation

@reinrich
Copy link
Member

@reinrich reinrich commented Feb 2, 2026

This pr introduces a new experimental option G1HumAllocPercentUntilConcurrent that 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

8355972: G1: Exclusive humongous allocations trigger unnecessary Full GC

doesn't show full gcs if the enhancement is enabled with -XX:+UnlockExperimentalVMOptions -XX:G1HumAllocPercentUntilConcurrent=30

Full command:

java -Xmx1g -Xlog:gc* -XX:+UnlockExperimentalVMOptions -XX:G1HumAllocPercentUntilConcurrent=30 HumongousGc.java

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

@SapMachine
Copy link
Member

Hello @reinrich, this pull request fulfills all formal requirements.

Copy link
Member

@RealCLanger RealCLanger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a formal review, not a technical one. For that, @schmelter-sap or @TheRealMDoerr, please have a look. Thx.

@reinrich
Copy link
Member Author

reinrich commented Feb 5, 2026

Thanks Christoph. I've pushed the requested changes.

@SapMachine
Copy link
Member

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, \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about G1MixedGCHumongousAllocThreshold? That name is similar to other options above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

@schmelter-sap schmelter-sap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more cosmetic remarks. Looks good otherwise.

}

// 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name makes it look like it does ending the phase instead of just deciding if it should be stopped.

(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))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't that change the log output for all kinds of GC causes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this disturb anyone who is parsing the logs? Otherwise, the change looks fine to me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be. I've reverted my change but kept the new output for the new case _g1_humongous_allocation.

@reinrich
Copy link
Member Author

reinrich commented Feb 5, 2026

Thanks for the reviews! Please have a look at the commits where I addressed them.

@SapMachine
Copy link
Member

Hello @reinrich, this pull request fulfills all formal requirements.

@SapMachine
Copy link
Member

Hello @reinrich, this pull request fulfills all formal requirements.

Copy link
Member

@TheRealMDoerr TheRealMDoerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a helpful feature. The implementation LGTM. I've checked that the test fails without the fix and passes with it.

@reinrich
Copy link
Member Author

reinrich commented Feb 6, 2026

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.

@RealCLanger
Copy link
Member

Please squash when merging. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants