RFR: 8231269: CompileTask::is_unloaded is slow due to JNIHandles type checks
Aleksey Shipilev
shade at openjdk.org
Tue Mar 18 14:29:45 UTC 2025
On Wed, 12 Mar 2025 19:45:41 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:
> [JDK-8163511](https://bugs.openjdk.org/browse/JDK-8163511) made the `CompileTask` improvement to avoid blocking class unloading if a relevant compile task is in queue. Current code does a sleuth-of-hand to make sure the the `method*` in `CompileTask` are still valid before using them. Still a noble goal, so we keep trying to do this.
>
> The code tries to switch weak JNI handle with a strong one when it wants to capture the holder. Since we are reusing the same field, we have to do type checks like `JNIHandles::is_weak_global_handle(_method_holder)`. Unfortunately, that type-check goes all the way to `OopStorage` allocation code to verify the handle is really allocated in the relevant `OopStorage`. This takes internal `OopStorage` locks, and thus is slow.
>
> This issue is clearly visible in Leyden, when there are lots of `CompileTask`-s in the queue, dumped by AOT code loader. It also does not help that `CompileTask::select_task` is effectively quadratic in number of methods in queue, so we end up calling `CompileTask::is_unloaded` very often.
>
> It is possible to mitigate this issue by splitting the related fields into weak and strong ones. But as Kim mentions in the bug, we should not be using JNI handles here at all, and instead go directly for relevant `OopStorage`-s. This is what this PR does, among other things that should hopefully make the whole mechanics clearer.
>
> Additional testing:
> - [x] Linux x86_64 server fastdebug, `compiler/classUnloading`, 100x still passes; these tests are sensitive to bugs in this code
> - [x] Linux x86_64 server fastdebug, `all`
> - [x] Linux AArch64 server fastdebug, `all`
You can model the impact it has on Leyden-style scenarios by producing many compile tasks with `-Xcomp`. For example, on my 5950X desktop and simple "Hello World" program that involves lots of javac compilation:
Benchmark 1: build/linux-x86_64-server-release/images/jdk/bin/java -Xcomp -XX:TieredStopAtLevel=1 Hello.java
# Before
Time (mean ± σ): 1.944 s ± 0.011 s [User: 1.822 s, System: 0.154 s]
Range (min … max): 1.924 s … 1.956 s 10 runs
# After
Time (mean ± σ): 1.914 s ± 0.008 s [User: 1.794 s, System: 0.151 s]
Range (min … max): 1.900 s … 1.923 s 10 runs
The effect is mostly due to avoiding `OopStorage` locks mentioned in PR body.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/24018#issuecomment-2729534004
More information about the hotspot-compiler-dev
mailing list