As release 1.3 of Clojure is on its way, I decided to give the currently available alpha4 a try and see some of the good stuff it brings. First thing first, I wanted to experiment myself with the performance gain that the extended support for native types would bring. I ran into an old post from which I got the inspiration for the specific test to run: the Takeuchi function.
The Java implementation for Tak provided me with a bottom line for performance comparison: Then I used the Clojure version provided in the original blog post run to test against Clojure 1.2:
Finally, I leveraged the new syntax for the enhanced primitives support to test against Clojure 1.3 (thanks to neotyk to point that out to me):
As you can see, timing is tracked from the application code, as various accessory overhead like JVM and Clojure runtime bootstrap are not in the scope of this post.
As this benchmark is “just for fun”, I won’t pretent I did an extensive benchmark, or that I engineered a bullet proof benchmark strategy and the like. I just ran the above code some tens of times and here follows the average running time for the three versions:
NOTE: an updated benchmark is provided down below NOTE2: to have a more fair performance comparison, keep reading
The results tells of a ~4.5x speed gain, getting close to match plain Java code performance.
Now, even if such a benchmark won’t be any news to the Clojure community, it’s still absolutely awesome to see such a performance gain in the next release of this beautiful Lispy language :-)
Update: following the advice by Jürgen Hötzel in his comment, I slightly modified my Clojure sources to change clojure.core/-
with clojure.core/unchecked-subtract
and re-run the test. Here’s the final results, which are way better for Clojure, especially for version 1.2:
Update 2: the following graph shows the impact of the direct use of the recur
special form tested against plain recursive invocation of Tak, as per requested in some comments
Update 3: even if this all started as a quick&dirty, amatorial benchmark, it attracted quite some attentions, demanding more fair and precise benchmarks, especially on the Java vs Clojure comparison. As in the Java version of Tak I used Integers and not primitive types, there is an unfair burden Java had to carry along the computation. The following is the result of a re-run of the test for Java (using primitive long) and Clojure 1.3: