GraalVM — Byte Code to Bit Code
GraalVM & Micronauts — frenzy way to MicroServices, Serverless: Part1
Early adopters for Cloud-Native ( microservices, serverless ) are now moving to its next wave called v2.x. leveraging the maturity, learnings, and identified shortfalls to design next-level stuff.
Let’s recap few purposes of going cloud-native that we will relate here:
- Scalability
- Cost — Memory vs Runtime
- Start-up & execution time ( cold start in Serverless )
- Throughput
- Enable polyglot
The current era of microservices is dominated by Java + other JVM based languages by large. Beside JVM’s super-rich ecosystem of libraries, frameworks, community support etc. few observation like thick memory footprint, cold startup & extended execution time, less polyglot support factored engineers for moving away from JVM platforms towards non-JVM stuff like nodeJs, Go-Lang, Python for cloud-native ecosystem.
GraalVM — An Oracle Labs initiative in collaboration with open source community supported by (VMWare, Red Hat, Microsoft, Twitter, Amazon and more.). To quote from their website :
It is a new universal virtual machine that supports a polyglot runtime environment and the ability to compile Java applications down to native machine code. GraalVM removes the isolation between programming languages and enables interoperability in a shared runtime.
Why the community is enthusiastic about GraalVM?
“GraalVM — Byte code to Bit Code” 😀😀
- GraalVM — Accelerating Application Performance :
GraalVM a modern JVM build on Oracle Java SE can improve the performance of any application written in Java or JVM without any single line change in existing code. It reduces the response time of end-user that in turn free up CPU, memory consumption and can be better utilized for more capacity and load handling. - GraalVM — Highly Optimized Compiler
The GraalVM compiler is highly optimized to enhance the pre-written application or the new one with its 62 separate compiler optimization algorithms (called “Phases”), of which 27 are patented. Many JVM languages (e.g., Java, Scala, Kotlin) will see around a 30%–40% speedup using GraalVM when compared with Java SE-8.
3. GraalVM — “Native imaging”
GraalVM “Native imaging” allows ahead of time compilation of Java code to a standalone executable called “native image”. It includes the application classes, classes from its dependencies, runtime library, classes from JDK and statically linked native code from JDK by using AoT (ahead-of-time compiler) for a specific operating system and architecture directly. It does not run on the Java VM, but includes necessary components like memory management and thread scheduling from a different virtual machine called “Substrate VM”.
GraalVM Native image supports JVM-based languages, e.g. Java, Scala, Kotlin etc.GraalVM native binary executables have incredibly fast load and execution time(since program initialisation can be done at build time and the application is already compiled) and much smaller footprint (since the JVM and JIT compiler don’t have to be distributed).
This is especially important during a cold start (e.g. serverless on demand start-up) as there is really no time to waste waiting for Spring Boot, JRE to configure itself. In this case, the system would already face a considerable backlog of events to process.
In case of GraalVM, it needs to know in advance which bytecode is going to be executed. Features like runtime dependency injection (on which Spring Boot relies heavily) will not work out of the box. Instead, a framework like Micronaut (which uses compile time dependency injection, proxy objects etc.) can be leveraged. In addition, the time it takes to create a native image is quite considerable. A typical compilation to a native image might take several minutes, so this step is one you would like to do e.g. during a nightly build.
export GRAALVM_HOME=
export PATH=$GRAALVM_HOME/bin:$PATH
# gu is the Graal Updater, it is used for installing additional packages,in this case the package for building native images
gu install native-image
# mn- Micronauts framework to leverage Native-Image
native-image --no-server -cp target/demo-mn-0.1.jar
One can build a native image directly with Maven using the
mvn package
command without running thenative-image
plugin.
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>${graalvm.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>example</imageName>
<buildArgs>
--no-fallback
</buildArgs>
</configuration>
</plugin>
4. Substrate VM — a subproject within Graal (VM)
“Native-Image” code does not run on Java VM, but includes necessary components like memory management and thread scheduling from a different virtual machine, called “Substrate VM”. It is a native runtime component (like the deoptimizer, garbage collector, thread scheduling etc.). The resulting program has faster startup time and lowers runtime memory overhead compared to a Java VM.
5. GraalVM’s — ( Ahead of Time Compiler) AoT vs OpenJDK’s JIT
This just-in-time compilation understands the workload over time and optimize the final code depending on its nature. That’s the reason why over time the JVM is considered more performant than native executables doing the same.
Features like reflection and proxies, heavily used by dependency injection centered frameworks such as Spring, pose a serious challenge for AoT compilation.
Hotspot JVM JIT is like a Diesel engine vs Petrol engine (AoT)
Those relationships require to be manually declared in configuration to allow the compiler know about them — you guessed it — ahead of time.
Recently, two new JVM frameworks based onGraalVM with this approach in mind: Micronaut and Quarkus.
6. GraalVM — MicroService & Serverless — for CloudNaitve EcoSystem
Microservices and serverless architectures are being implemented or are part of the roadmap in most modern solution stacks. Given that Java is still the dominant language for business applications, the need for reducing the startup time for Java is becoming more important. Serverless architectures are one such area that needs faster startup time along with applications hosted on the container platform.
Several projects have accepted GraalVM Native Image as a platform for their applications like Quarkus, Micronaut. Spring Framework recently announced the upcoming support for native images.
7. GraalVM — Execution and Start-up time
“Loading Time Affects Your Bottom Line”
GraalVM allows you to compile a program ahead of time into a native executable that runs with Substrate VM. Substrate VM is written in Java and compiled into the native executable. The resulting program has faster startup time and less runtime memory overhead compared to a Java VM.
We measured the startup and memory footprint of a basic microservice build in Micronaut.
My GitHub Repo for Demo Apps build with Micronauts for benchmarking :
https://github.com/scanpratik/micronauts-GraalVM--JIT
https://github.com/scanpratik/micronauts-nativeImage-GraalVM
https://github.com/scanpratik/graalVM-SpringBoot2.X
8. GraalVM Polyglot Runtime
“Truffle Language Implementation Framework”
A new language implementation framework called Truffle makes it possible to implement language interpreters that are both simple and high performance. So GraalVM is not only a JIT compiler and ahead-of-time native compiler for Java, but it can also be a JIT compiler for JavaScript, Ruby, R, and Python. Polyglot embeddings can also be compiled ahead-of-time.
Your pom.xml
file as for using Truffle plugin :
<dependency>
<groupId>org.graalvm.truffle</groupId>
<artifactId>truffle-api</artifactId>
<version>20.1.0</version> <!-- or any later version -->
</dependency>
<dependency>
<groupId>org.graalvm.truffle</groupId>
<artifactId>truffle-dsl-processor</artifactId>
<version>20.1.0</version>
<scope>provided</scope>
</dependency>$ gu install native-image
$ gu install ruby
$ gu install python
$ gu install R
Cloud-Native Microservices, Serverless — Design Decision :
Sometimes good performance means good throughput, sometimes it means low memory usage, and sometimes it means a fast cold-start startup time.
GraalVM vs Hotspot VM ( OpenJDK) — A Trade-offs while selecting Native Image:
Benefits of “Native-image” aren’t for free — they come with a cost.
Obviously the native executable can only run on a single platform. Another limitation is caused by missing metadata during runtime. Since by default native image doesn’t retain information about classes and methods, hence one’s ability to perform reflection is limited. As there are many Java frameworks that rely on reflective access, getting them run on Native Image may require additional configuration.
Let’s see in next section, Part2 — how next wave of Microservices and Serverless are getting build based on modern frameworks like Micronaut build on GraalVM.