RFR: 8340434: Excessive Young GCs Triggered by CodeCache GC Threshold
sli-x
duke at openjdk.org
Wed Feb 19 06:21:33 UTC 2025
The trigger of _codecache_GC_threshold in CodeCache::gc_on_allocation is the key to this problem.
if (used_ratio > threshold) {
// After threshold is reached, scale it by free_ratio so that more aggressive
// GC is triggered as we approach code cache exhaustion
threshold *= free_ratio;
}
// If code cache has been allocated without any GC at all, let's make sure
// it is eventually invoked to avoid trouble.
if (allocated_since_last_ratio > threshold) {
// In case the GC is concurrent, we make sure only one thread requests the GC.
if (Atomic::cmpxchg(&_unloading_threshold_gc_requested, false, true) == false) {
log_info(codecache)("Triggering threshold (%.3f%%) GC due to allocating %.3f%% since last unloading (%.3f%% used -> %.3f%% used)",
threshold * 100.0, allocated_since_last_ratio * 100.0, last_used_ratio * 100.0, used_ratio * 100.0);
Universe::heap()->collect(GCCause::_codecache_GC_threshold);
}
}
Here with the limited codecache size, the free_ratio will get lower and lower (so as the threshold) if no methods can be swept and thus leads to a more and more frequent collection behavior. Since the collection happens in stw, the whole performance of gc will also be degraded.
So a simple solution is to delete the scaling logic here. However, I think here lies some problems worth further exploring.
There're two options to control a code cache sweeper, StartAggressiveSweepingAt and SweeperThreshold. StartAggressiveSweepingAt is a sweeper triggered for little space in codeCache and does little harm. However, SweeperThreshold, first introduced by [JDK-8244660](https://bugs.openjdk.org/browse/JDK-8244660), was designed for a regular sweep for codecache, when codeCache sweeper and heap collection are actually individual. After [JDK-8290025](https://bugs.openjdk.org/browse/JDK-8290025) and some patches related, the old mechanism of codeCache sweeper is merged into a concurrent heap collection. So the Code cache sweeper heuristics and the unloading behavior will be promised by the concurrent collection. There's no longer any "zombie" methods to be counted. Considering it will introduce lots of useless collection jobs, I think SweeperThreshold should be deleted now.
-------------
Commit messages:
- remove SweeperThreshold and set it to Obselete
Changes: https://git.openjdk.org/jdk/pull/21084/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=21084&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8340434
Stats: 55 lines in 14 files changed: 1 ins; 53 del; 1 mod
Patch: https://git.openjdk.org/jdk/pull/21084.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/21084/head:pull/21084
PR: https://git.openjdk.org/jdk/pull/21084
More information about the serviceability-dev
mailing list