This is in response to a series of tweets by Chouser regarding java/clojure/python startup time for dynamically parsing a small code snippet.
https://twitter.com/chrishouser/status/826881223486226432
https://twitter.com/chrishouser/status/826884726485032960
(bench results are normalized to my dev environment)
CODE='(-> {:parse {:some :data}} :parse :some)'
time java -jar clojure-1.8.0.jar -e "$CODE"
0m1.018s
CODE='({"parse": {"some": "data"}})["parse"]["some"]'
time python -c "print $CODE"
0m0.016s
I initially suspected the poor showing for Clojure/JVM could mostly be attributed to clojure.jar
and not the JVM. A quick POC in Java parsing {"parse": {"some": "data"}}
(JSON) is roughly 10x faster than the example.
But to be fair to Clojure, this example is parsing and executing code not data. So this gist provides the semantic equivalent of what Clojure, Python, and Node.js are doing in pure Java.
time java pmbauer.JavaIsKindaLight
0m0.471s
Okay, so Clojure isn't adding that much overhead. We're still several orders of magnitutde slower than python.
But why? Is it because the Java and Clojure versions are writing to disk and the python version isn't? Well ...
strace -r java pmbauer.JavaIsKindaLight
0.000000 execve("/usr/bin/java", ["java", "pmbauer.JavaIsKindaLight"], [/* 115 vars */]) = 0
0.000288 brk(NULL) = 0x10d1000
0.000034 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
...
0.000037 futex(0x7fdc1b2a19d0, FUTEX_WAIT, 7052, NULLdata
) = 0
0.842562 exit_group(0) = ?
0.002464 +++ exited with 0 +++
futex -> exit_group
is taking up the vast majority of execution time; all of the real work is already done, java is just blocked exiting on thread cleanup. IO appears to be a non-factor.
The minimal example and Clojure both exhibit this profile and simple Java applications that don't dynamically compile code do not.