RFR(M): 8244660: Code cache sweeper heuristics is broken
Nils Eliasson
nils.eliasson at oracle.com
Fri May 8 15:31:30 UTC 2020
Hi,
In a recent bug (JDK-8244278) it was discovered that the heuristics for
StartAggressiveSweepingAt was wrong. Aggressive sweeping means that the
sweeper is trying to start a sweep for every new allocation. With
default settings before the fix, aggressive sweeping started at already
at 10% full.
However with the fix applied - there was no sweeps at all. This is also
wrong - the sweeper should trigger regularly. The problem is that the
sweeper thread is sleeping and there were no code path in which it was
awakened (except through StartAggressiveSweepingAt). So the counters
counted, thresholds were reached, but the sweeper slept on.
Investigating this I encountered the next problem. The old heuristics
had two different thresholds:
1) Number of safepoints with stack scans.
With the transition to handshakes from safepoints we can no longer rely
on safepoints happening. I have removed all of that code.
2) number of bytes of nmethods that had been marked as zombie or not
entrant (see NMethodSweeper::possibly_enable_sweeper). This is now the
only regular way that sweeps are triggered. (The other two are
aggressive sweeping and whitebox testing).
I changed the threshold test to be against a new flag -
SweeperThreshold. This is because users with different sized code caches
might want different thresholds. (Otherwise there would be no way to
control the sweepers intensity).
The default is MIN2(1 * M, ReservedCodeCacheSize / 256));
At default tiered ReservedCodeCacheSize that is about 1M.
At a small code cache of 40M that is about 150k
The threshold is capped at 1M because even if you have an enormous code
cache - you don't want to fragment it, and you probably don't want to
commit more than needed.
This patch simplified the sweeper quite a bit. Since the sweeper only is
awaken when there is actual job - no more complex heuristics is needed
in the sweeper thread. This also has the benefit that the sweeper will
always sleep when there is no job.
To be able to notify the sweeper thread from
NMethodSweeper::possibly_enable_sweeper I had to use a different monitor
than CodeCache_lock. I added a new monitor that replaces the
CodeCache_lock for signaling. This monitor (CodeSweeper_lock) is only
used for signaling the sweeper thread - and the lock is always released
before doing anything else.
With this patch - JDK-8244278 can be applied on top to fix the
aggressive sweeping, and the sweeper will continue to work.
This path applies on top of JDK-8244658 that removes dead code in the
sweeper.
Bug: https://bugs.openjdk.java.net/browse/JDK-8244660
Webrev: http://cr.openjdk.java.net/~neliasso/8244660/webrev.01/
Please review,
Nils Eliasson
More information about the hotspot-compiler-dev
mailing list