![]() ![]() However, this requires some care, and some parts of the core library initialization need to be delayed to, or patched at, runtime because they depend on the runtime environment.įor instance, setting $$ (the PID global variable) must be done at runtime, otherwise it would reflect the PID of the Native Image Generator process, which is no longer running. We call this step pre-initialization and this is actually available for any GraalVM-based language. Yes we can, with SubstrateVM, and that’s how we got to 25ms startup! Since we can read files and parse Ruby code ahead-of-time, could we also evaluate Ruby code ahead-of-time?Ĭould we load the entire core library Ruby code during Native Image Generation? Pre-Initialization and Freezing the Entire Heap with Native Image That’s still significantly slower than MRI, so we need to go deeper. This gives another boost for startup, producing Hello World in around 96ms. It turns out, we could both read the files and parse them to ASTs ahead-of-time, in a static initializer, while SubstrateVM is compiling our Java code! Reading these 89 files from disk takes time, but further than that, parsing them to Abstract Syntax Trees (ASTs) is also time-consuming. The core library in TruffleRuby is defined mostly in Ruby (similar to Rubinius) and as a result there are about 18 000 significant lines of Ruby code to load, on every startup, before executing any user Ruby code. One prime example here for TruffleRuby is storing the Ruby files of the core library. This gives the opportunity to run additional initializations ahead-of-time and store the resulting state in static (class) variables. SubstrateVM not only compiles Java classes ahead-of-time, it also executes the static initializers (corresponding to statements in the class/ module body in Ruby). This is not new, and Kevin Menard already discussed it in a blog post two years ago, but it is an important context to discuss further startup optimizations. Having all Java methods precompiled to native code, rather than executing them in the Java interpreter and then JIT’ing some of them.Not having to load Java classes at runtime.That step alone reduces startup time to around 165ms. truffleruby-1.0.0-rc16/bin/trufflerubyĪt runtime, the application will then start with the main() method, but no classloading or JIT compilation of Java classes is needed every Java method is already compiled to native code and ready to be run. This native code is stored in a native executable, i.e., a “Native Image”.įor instance, TruffleRuby is written in Java and Ruby, and all Java classes are compiled ahead-of-time into a native executable: ![]() This is done once during a step called Native Image Generation, where SubstrateVM will look at the classpath, include every reachable class and compile those classes and methods to native code, all of that ahead-of-time. ![]() SubstrateVM, unlike, for example, HotSpot, loads all Java classes ahead-of-time, not at runtime. The first and biggest step goes from 1787ms to 165ms (10x faster) by using a custom VM called SubstrateVM. Ahead-Of-Time Compilation with Native Image I just use my Ruby manager ( chruby), switch to each ruby and run Hello World.įWIW, I think this kind of startup tricks is usually cumbersome to setup and therefore rarely used and not representative of what most users experience. Note that I do not consider any trick to improve startup time here like having a prepared JVM process around ( nailgun, drip, etc). Precise-time is a small C program I wrote to measure startup time precisely using clock_gettime(CLOCK_MONOTONIC). $ precise-time 10 `which ruby` -e 'puts "Hello World"' ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |