FourthGraalAdventures
From APIDesign
Yet another year or two passed since TwoYearsWithTruffle article was written and it is time to summarize list of my recent Graal adventures again.
Contents |
Collecting profiles for guided optimizations
SubstrateVM (enterprise edition) had an ability to instrument its code and dump profiling information to disk. While useful in a testing environment, the requirements of a cloud based deployments are different. The same application is supposed to be distributed among multiple docker containers running on multiple nodes. As such I was working on enhancing our central agent server - called **gemasrv** - to be able to request, obtain and track the PGO data over the wire from multiple applications.
However even this simplification wasn't good enough for projects like Helidon or FnProject. People don't want to debug and test the HotSpot version of the application, then build first (and slow) native image with profiling on to gather data about real usage from the VM and only then produce the production ready version. That is too complex and requires orchestration between developers, admins and operations. Rather than that let's collect the profiles in HotSpot mode of GraalVM EE! As such I introduced -Dgraal.ProfilesCollectExperimental=true option that collects the profiling data and exposes them via dedicated Graal compiler JMX bean. The option can even be turned on remotely, when needed.
With this kind of setup the whole orchestration of the containers is simplified. Developement produces JAR files of the application and operations can distribute them to [Docker]] containers. When needed, they can selectively enable the profiles gathering via a remote JMX connection. Later they can retrieve the collected data via the same JMX connection and provide them back to development to use them when generating the final NativeImage binary.
This all was working in GraalVM EE 1.0 RC14. Since RC15 it needs an additional option --jvmci:-UseNativeCompiler to (temporarily) disable the libgraal compiler.
Universal Secure Scripting API
Nashorn got deprecated in JDK11. As such the NetBeans community started to seek a replacement. I started to work on universal Scripting API. There was no need to hurry until CVE-2018-17191 was reported. Then we needed an immediate action. The community tried to empower Rhino, but at the end we settled with a secured solution based on Nashorn with the path paved to switch to Graal.js - the scripting engine based on GraalVM and Truffle.
Graal.js has been fully relicensed to a benevolent Universal Public License. That allowed NetBeans 11 to include Graal.js and offer it as a JavaScript engine that one can request via the Scripting API. The goal is to use the Graal.js engine everywhere instead of deprecated Nashorn. That however required me to further stress the security part of the story. I decided to tighten up the JavaScript access to Java code by implementing HostAccess and setting the default to EXPLICIT. That shall prevent accidental access to various Java methods by following the rule of least privilege. E.g. only methods annotated by @Explicit annotation are exposed to the potentially vulnerable script.
The Scripting is universal. E.g. it allows one to embed any language, not just JavaScript as the following tutorial in package-summary shows.
Fixing the vulnerability, polishing Graal.js and Truffle for inclusion into NetBeans kept me busy for half a year. Switching NetBeans to the latest version of GraalVM still remains on my TODO list.
Java as the Universal Language
Every year I try to prepare a new presentation. This year I decided to focus on SubstrateVM and its usage in Docker and cloud. That resulted in my current Forget Go. Go, Java, go! show:
The first part compares Go and Java with NativeImage based solution. Common stuff. However, it is the second part (at 23rd minute) when things get interesting. The second part shows how to easily bridge two different oceans - the ocean of Java and the ocean of C libraries.
I have created the Matrix the Ultimate project which uses GNU Scientific Library written in C to hold representation of a matrix and then tries to access such data structure from Java effectively. There are few options: JNI, JNA, JNI over SubstrateVM, and SubstrateVM based one. The most comfortable solution is JNA, but it is also very slow compared to compiling everything into native code - its is 50x slower. JNI and JNI over SubstrateVM can bridge the two oceans more effectively, but they are still twice as slow as the final solution - that solution uses the singletonizer pattern to move the algorithm where the data are - e.g. use the same Java algorithm in NativeImage generated library. That of course gives us the full speed while allowing us to keep the rest of the application in classical HotSpot JVM.
In some sense this is a replacement for the Panama project. While using the SubstrateVM capabilities to access C structures, we can eliminate any boundaries between Java and C caused by classical JNI. We can write JNI in Java on both sides of the canal - e.g. use Java as an Universtal language - as the managed language as well as the native language.
Of course, achieving that required few fixes in the StackValue and especially introduction of CEntryPoint.Builtin builtin. Then the Matrix the Ultimate magic become possible.
Minors
- Teaching a course at MatFyz: Practical Dynamic Compilation
- Self Language, https://github.com/JaroslavTulach/SelfGraal/compare/master...PEParser
- Talk 2 compiler: https://github.com/jaroslavtulach/talk2compiler
- Graal.js maven archetype updates