-
Enhancement
-
Resolution: Unresolved
-
P4
-
23
CodeCache is dynamic. Code comes in and out. Code can be used most of the time. Code can be used periodically. Code can be used some time and never used after. Frequently called code can be spread across CodeCache and become sparse. From performance analysis of applications affected by sparse code we know sparse code mostly affects prediction of calls. CPU branch predictor might be less effective in case of sparse code. On Graviton systems code sparsity can be measured: https://github.com/aws/aws-graviton-getting-started/blob/main/perfrunbook/debug_hw_perf.md#drill-down-front-end-stalls.
We spend 80-90% in C2 nmethods. Most of frequently called Java methods will be C2 nmethods. C2 nmethods don't collect profiles. To reduce sparsity of C2 nmethods we need to detect those nmethods and group them together. A group of nmethods can change. Some of nmethods can stop being frequently called. We need to remove such nmethods from a group.
At high level the process is:
- We detect frequently called C2 nmethods.
- We relocate them close to each other.
- We remove C2 nmethods from a group if they are not frequently called.
We need a JMH benchmark to measure impact of sparse code.
## Detection of frequently called C2 nmethods
We need detection of frequently called C2 nmethods to be precise enough to detect major Java methods. Low overhead is more important than precision.
We can a sampling thread which uses the thread-local handshake framework. An example of such a thread is the Sweeper: https://github.com/openjdk/jdk17u/blob/master/src/hotspot/share/runtime/sweeper.hpp which was used to detect active nmethods.
## Relocation of frequently called C2 nmethods
Currently we can relocate a nmethod to a new place only through deoptimization and recompilation. Recompilations, especially C2, are expensive. Having many of them can cause performance issues. Also recompiled code might differ from the originally compiled code.
Instead of recompilations we need copy like recolations where we copy a nmethod to a new place and relink its code.
We need to group nmethods somewhere. We can group them in the same code heap which they belong to. Or we can use a separate code heap. Support of a separate code heap is simpler to implement. From public benchmark and real-life applications we estimate that nmethods to group will be ~10%-20% of all nmethods. So a separate code heap won't need a lot of memory.
We can consider not to relocate some nmethods if they are already close to each other.
## Removal of nmethod from a group
Currently GC is responsible for flushing nmethods from CodeCache.
We can either of:
- Mark nmethods needed to be removed as cold and rely on GC to flush them.
- Exclude the special code from GC flushing. Copy nmethods back to a general code heap.
We spend 80-90% in C2 nmethods. Most of frequently called Java methods will be C2 nmethods. C2 nmethods don't collect profiles. To reduce sparsity of C2 nmethods we need to detect those nmethods and group them together. A group of nmethods can change. Some of nmethods can stop being frequently called. We need to remove such nmethods from a group.
At high level the process is:
- We detect frequently called C2 nmethods.
- We relocate them close to each other.
- We remove C2 nmethods from a group if they are not frequently called.
We need a JMH benchmark to measure impact of sparse code.
## Detection of frequently called C2 nmethods
We need detection of frequently called C2 nmethods to be precise enough to detect major Java methods. Low overhead is more important than precision.
We can a sampling thread which uses the thread-local handshake framework. An example of such a thread is the Sweeper: https://github.com/openjdk/jdk17u/blob/master/src/hotspot/share/runtime/sweeper.hpp which was used to detect active nmethods.
## Relocation of frequently called C2 nmethods
Currently we can relocate a nmethod to a new place only through deoptimization and recompilation. Recompilations, especially C2, are expensive. Having many of them can cause performance issues. Also recompiled code might differ from the originally compiled code.
Instead of recompilations we need copy like recolations where we copy a nmethod to a new place and relink its code.
We need to group nmethods somewhere. We can group them in the same code heap which they belong to. Or we can use a separate code heap. Support of a separate code heap is simpler to implement. From public benchmark and real-life applications we estimate that nmethods to group will be ~10%-20% of all nmethods. So a separate code heap won't need a lot of memory.
We can consider not to relocate some nmethods if they are already close to each other.
## Removal of nmethod from a group
Currently GC is responsible for flushing nmethods from CodeCache.
We can either of:
- Mark nmethods needed to be removed as cold and rely on GC to flush them.
- Exclude the special code from GC flushing. Copy nmethods back to a general code heap.
- relates to
-
JDK-8316694 Implement relocation of nmethod within CodeCache
-
- In Progress
-
-
JDK-8350852 Implement JMH benchmark for sparse CodeCache
-
- In Progress
-