-
Bug
-
Resolution: Fixed
-
P3
-
11, 12, 13, 14, 15
-
b26
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8247775 | 11-pool | Nils Eliasson | P3 | Closed | Duplicate |
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 ofJDK-8244658 that removes dead code in the sweeper.
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 -
This path applies on top of
- backported by
-
JDK-8247775 Code cache sweeper heuristics is broken
-
- Closed
-
- relates to
-
JDK-8244278 Excessive code cache flushes and sweeps
-
- Resolved
-
-
JDK-8245877 assert(_value != __null) failed: resolving NULL _value in JvmtiExport::post_compiled_method_load
-
- Resolved
-
-
JDK-8254185 Fix Code cache sweeper heuristics for JDK 11
-
- Resolved
-