-
Notifications
You must be signed in to change notification settings - Fork 54
8368465: [leyden] Improve precompiler method selection code #99
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: premain
Are you sure you want to change the base?
8368465: [leyden] Improve precompiler method selection code #99
Conversation
|
javac test (1000 iterations trained, 50 iterations production)
|
|
👋 Welcome back shade! A progress list of the required criteria for merging this PR into |
|
Larger benchmarks all improve with 1-core tests. quarkus-getting-started: helidon-quickstart-se micronaut-first-app spring-boot-getting-started: spring-petclinic: |
|
❗ This change is not yet ready to be integrated. |
Webrevs
|
|
Ready for review, folks. There are performance benefits of doing this, very apparently. |
vnkozlov
left a comment
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.
Few questions
| if (mtd != nullptr) { | ||
| MethodData* md = mtd->final_profile(); | ||
| if (md != nullptr) { | ||
| count += md->backedge_count(); |
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.
Hmm, this will put methods with hot loop up front.
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.
Yes, this is intentional: this effectively puts the methods that are profitable to (pre)load first, so they: a) do not linger in interpreter too much; b) do not trigger JIT compilation before AOT code is able to (pre)load. The methods with hot back-branches are those methods :)
|
|
||
| default: fatal("%d", _search_level); | ||
| } | ||
| // Otherwise, break the tie by code size: largest methods go first. |
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.
What is the reason for larger method be first? Can we use compile ID here instead?
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.
So my logic was like with the hot methods. If we have lost the game of "preload the AOT code before JIT got triggered", and JIT got triggered, we want to then prioritize larger methods, as they are more likely to take more time to JIT compile. In other words, I think if you lost to JIT timing-wise, you want to preempt the fattest JIT compiles first. But it is only a bet. If we ever record compilation time in nmethods/profiles, we could have used that to break the tie.
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 am not sure understand how different order of pre/AOT-compilation can affect performance of production run.
We bulk load all "Preload" AOT code - ordering does not matter for it. Even if we load in selected order. It is one thread which do loading and it is blocking (I actually playing with spreading this preload on all compiler threads - did not see much affect on startup).
The only explanation is that preload happens only when C2 compiler threads are initialized (Preload AOT code is C2 compiled code) and it happens simultaneously with C1 threads initialization which could be available sooner for C1 compilation than we finish preloading. Especially on small number of cores machines. I did observed that we start loading A1 and A2 code first (even normal C1 compilations) before we start preload AP4.
Is it what you are trying to solve here?
The invocation counters should be roughly the same for methods without loops (10000 to trigger C2 compilation). They could be different if code was deoptimized and run in interpreter. The only difference id backedge counter. So in this sense you push methods with hot loop up front as we talked about in other comment. Which may affect performance but it would depend on application.
I agree with ordering by size (or time spant in compilation) but only for methods which did not have A1 or A2 code. Which should not be the case - if we have AP4 we will have A1 and A2 for it. I am still not convince by this.
May be we should try to move AOTCodeCache::preload_code() just after SystemDictionary::compute_java_loaders() because it does not depend on training data. So we can have AP4 sooner. MMaping directly into CodeCache will also speedup preloading - it is on our list to do.
|
I think we have small performance "issue" how we replace existing JITed code with new one which AOT code loading could be more sensitive. We deoptimize old code before new code is set under lock If lock is held by other thread we may deoptimize previous code and go into interpreter before new code is set for use. This is present in mainline but with normal JIT compilation replacement it may be not noticeable. |
|
An other suggestion for this concurrent preloading would be to split A4 preload code. One set is the current which needs to wait |
|
@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 |


Forked from JDK-8366681: there are still some cleanups/performance improvements possible. Current selection code is a bit hairy, and turns out the changes I made for previous patch improve performance.
Notable improvements:
Additional testing:
runtime/cdsProgress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/leyden.git pull/99/head:pull/99$ git checkout pull/99Update a local copy of the PR:
$ git checkout pull/99$ git pull https://git.openjdk.org/leyden.git pull/99/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 99View PR using the GUI difftool:
$ git pr show -t 99Using diff file
Download this PR as a diff file:
https://git.openjdk.org/leyden/pull/99.diff
Using Webrev
Link to Webrev Comment