Skip to content
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

Small corrections to story #2071

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions _posts/2024-08-06-quarkus-and-leyden.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ You might have heard of https://openjdk.org/projects/leyden/[Project Leyden], a

As Quarkus users, you'll be wondering how this project will benefit you and how it's different from GraalVM native images. While we think it's fair to say that Leyden was inspired or at least motivated by some ideas first implemented in GraalVM's native images, Leyden is remarkably different. It's essential to understand how it works: as we will see, Leyden is not a replacement for GraalVM native images but rather a substantial evolution of the JVM, and we expect it to bring some benefits to native images as well.

To try to clarify this, unfortunately, this post is unusually long: we wish it could have been a short guide, "This is how you enable Leyden," but this isn't quite the time yet, as we need to understand the different models first. Sometimes, the terminology is also different; for example, "Ahead of Time (AOT)" has a very specific meaning in the context of GraalVM native images and has traditionally been associated with "compilation", but in the context of Leyden it is used more broadly to indicate a variety of aspects of the JVM ; hopefully, after reading this, it will be less confusing.
To try to clarify this, unfortunately, this post is unusually long: we wish it could have been a short guide, "This is how you enable Leyden," but this isn't quite the time yet, as we need to understand the different models first. Sometimes, the terminology is also different; for example, "Ahead of Time (AOT)" has a very specific meaning in the context of GraalVM native images and has traditionally been associated with "compilation", but in the context of Leyden is used more broadly to indicate a variety of aspects of JVM operation; hopefully, after reading this, it will be less confusing.

Another significant misconception about Leyden is that it's a project to "improve startup times"; this statement is not wrong, as improving startup times is one of its goals. Yet the other stated goals of the project offer even more significant potential for our favourite platform, Quarkus, and its users.

Expand Down Expand Up @@ -134,16 +134,16 @@ This ability to fallback to "regular JIT processing" is a luxury that GraalVM na
Another well-known lazy operation the JVM performs is JIT (runtime) compilation. Method bytecode is normally interpreted, but the JVM will lazily translate bytecode to equivalent machine code.
Since generating optimal machine code is an expensive operation, it performs this compilation task selectively, only bothering to compile methods that have been invoked quite a few times.

JIT compilation is also 'adaptive' i.e. the JVM will also lazily upgrade compiled code after it has been executed very many times, using a different 'tier' or level of compilation:
JIT compilation is also 'adaptive' i.e. the JVM will lazily recompile some methods, using different 'tiers' or levels of compilation.

. An initial tier 1 compile runs quickly, generating code that is only lightly optimised using profile information gathered during interpretation.
. A tier 2 recompile will instrument the code to track more details about control flow.
. Tier 3 compilation adds further instrumentation that records many more details about what gets executed, including with what type of values.
. Finally a tier 4 compilation uses the gathered profile information to perform a great deal of optimization.
. A tier 1 compile generates code that is only lightly optimised, based on very limited execution profile data.
. A tier 2 compile also generates lightly optimized code but instruments it to profile control flow.
. Tier 3 compilation adds further instrumentation that records many more details about what gets executed, including with what type of values.
. A tier 4 compile uses all gathered profile information and performs a great deal of optimization.

This final stage of compilation can take a very long time so compilation above tier 1 only happens for a small subset of very frequently executed methods.
Tier 1 - 3 compilations omit many possible optimizations in order to deliver compiled code quickly. A tier 4 compilation can take much longer to complete so it is only attempted for a small subset of very frequently executed methods.

Sometimes, the code is compiled with substantial optimisations based on assumptions extrapolated from the profiling data.
Sometimes, the code is compiled with substantial optimisations based on 'speculative' assumptions extrapolated from the profiling data.
In such cases, the compiler will make an optimistic assumption about a condition to be consistently true in the future yet include an efficient check to verify the assumption during execution so that the semantics of the program are not affected in case this educated guess eventually turns out to be false; when this is detected, the code is de-optimised, returning at a previous tier of compilation and the profiling data is adjusted, so that it will eventually be recompiled with better information.
Essentially, some parts of code might get recompiled multiple times and occasionally revert to a lower tier: it's an highly dynamic process.

Expand Down