This blog will show you how I reduced the jvm startup time with 60%.
I wanted to use the jvm as base for scripting what I normally do in bash. But even the simplest ‘Hello world’ took about 697ms to execute. This takes about < 1ms if I use bash.
So I looked into the options I have to slim down the jvm startup time. The test I made was a ‘(println “Hello world.”)’, a small Clojure one liner.
The baseline, on the test system is:
java -Xbootclasspath/a:./clojure-1.8.0.jar clojure.main -e '(println "Hello world")' which took about 697ms.
If you add some jvm startup params it is getting a little bit better:
java -Xbootclasspath/a:./clojure-1.8.0.jar -XX:+TieredCompilation -XX:TieredStopAtLevel=1 clojure.main -e '(println "Hello world")' this will bring down the startup time to 545ms.
A reduction of about 20%. Not bad for two additional parms.
These two parms actual tell the jvm to behave as a -client instead of the default -server. I am on OSX and using a 64bit jvm on a server class system (>2 cpu and >2GB memory).
This was still not enough for me. I wanted to have an even faster startup. So at the end I ended up with this
java -Xbootclasspath/a:./clojure-1.8.0.jar -Xshare:on -XX:+TieredCompilation -XX:TieredStopAtLevel=1 clojure.main -e '(println "Hello world and CDS enabled and -client enabled")' which gave me a startup time of 271ms. A reduction down to 40% of the original 697ms.
That last step is based on Class Data Sharing, the reason I added
-Xshare:on. For some background information you can look at CDS.
CDS is a file which the jre writes its bootstrap classes into, to speed up the jvm startup. Not all jvm install programs create that file. So have a go and use
java -Xshare:dump. You will notice a different startup time already, if the jvm installer did not create this particular file.
For me I have added the clojure v1.8.0 classes to this CDS file and that’s the reason I went from 697ms downto 271ms (60% reduction) of startup time.
You need some shell scripting capabilities but follow the next script:
# start up the jre to generate its own cds file list
java -Xshare:dump -XX:DumpLoadedClassList=jre-cds-list
# generate our own cds list
jar -tf clojure-1.8.0.jar | grep class | sed 's/.class//g' > our-cds-list
# combine the two cds lists into one
cat jre-cds-list our-cds-list > combined-cds-list
# generate the new combined cds jsa file
java -Xbootclasspath/a:./clojure-1.8.0.jar -XX:SharedClassListFile=combined-cds-list -Xshare:dump
Happy coding. And don’t forget this is just for scripting not for long running java programs.