-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8231269: CompileTask::is_unloaded is slow due to JNIHandles type checks #24018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back shade! A progress list of the required criteria for merging this PR into |
@shipilev This change is no longer ready for integration - check the PR body for details. |
c8ec550
to
d4a23b8
Compare
You can model the impact it has on Leyden-style scenarios by producing many compile tasks with
The effect is mostly due to avoiding |
a3e0f91
to
052f54b
Compare
052f54b
to
cc8345e
Compare
Webrevs
|
/label hotspot-gc |
@dean-long |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, Aleksey!
What do you think about making 1 step further and encapsulating weak/strong reference handling into a helper class?
Also, as an optimization idea: seems like weak + strong handles form a union (none -> weak -> strong). So, once a strong reference is captured, corresponding weak handle can be cleared straight away.
Yes. I think @veresov would want to have some of this for persistent profiles JEP and I pushed the WIP thing into PR. That only covers the "method unload blocker" part. But I think it should really go further, and encapsulate
It turns out to be necessary to avoid touching |
Nice! I really like how it shapes out. |
Pushed the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel uneasy about all the complications introduced by coordination between accessors.
It looks like supporting concurrent release operation adds a lot of complexity.
Weak -> strong transition is monotonic, so shouldn't need as much care.
What do you think about making release operation part of CompileTask recycling (e.g., in UnloadableMethodHandle
destructor)? By the time it happens, there should not be any other users of the task. (Otherwise, recycling concurrently accessed task is unsafe anyway).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a drive by comment.
Not sure what our opinion is w.r.t. mutable
, but how do we feel about typing the spin lock as mutable
and keep is_safe()
and method*()
const. We can then keep the old signature for CompileTask::is_unloaded()
CompileTask::method()
and ArenaStatCounter::ArenaStatCounter(...)
.
I like this a lot! Dropping |
@shipilev this pull request can not be integrated into git checkout JDK-8231269-compile-task-weaks
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
@shipilev This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a |
Just a drive-by reply. |
Yes, I think this looks like the sort of thing I had in mind when we were discussing it back whenever that was. |
JDK-8163511 made the
CompileTask
improvement to avoid blocking class unloading if a relevant compile task is in queue. Current code does a sleight-of-hand to make sure the themethod*
inCompileTask
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 to block unloading. 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 toOopStorage
allocation code to verify the handle is really allocated in the relevantOopStorage
. This takes internalOopStorage
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 thatCompileTask::select_task
is effectively quadratic in number of methods in queue, so we end up callingCompileTask::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:
compiler/classUnloading
, 100x still passes; these tests are sensitive to bugs in this codeall
all
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/24018/head:pull/24018
$ git checkout pull/24018
Update a local copy of the PR:
$ git checkout pull/24018
$ git pull https://git.openjdk.org/jdk.git pull/24018/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 24018
View PR using the GUI difftool:
$ git pr show -t 24018
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/24018.diff
Using Webrev
Link to Webrev Comment