Wednesday, 25 July 2012

Clojure poor performance - why?

The only glaring result from my functional language benchmarking (a strong word for what I did in all honesty) is the Clojure result.

Now, let me be upfront here - I love Clojure. I've always loved the lisp family of languages, but always found Common Lisp a little clunky sometimes (although very quick). Clojure is great, it has all the benefits of the JVM, but with modern data structures and some good concurrency constructs. It's functional, immutable and has macros support (as you'd expect).

It's also dynamic, with lots of boxing going on if you're not careful. I thought this was the reason for the slowdown, but after doing a lot of optimising using type hints and the new numerics supports in 1.3 I got very little improvement in performance. I even dropped records and used maps, even though it's counter-intuitive...but all to no avail.

I thought it could be the trig and maths at fault, so the first thing I tried was to use memoize to cache the results of the travel calculations. However, this made only a small improvement.

It was when I commented out the various trig calls that I got a change in the results. It went down from 51s to 10s.

Right.

So I started to do some digging and came across the following:

https://blogs.oracle.com/jag/entry/transcendental_meditation
http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html

These seems to suggest it's not using the hardware fcos/fsin some/most of the time - that to achieve the JVM required accuracy software implementations are used.

Do some googling and you'll find many more articles on this.

So beware!

I'm still not sure why Scala doesn't seem to suffer? Maybe the libraries have workarounds?

But it gives me confidence that Clojure is close enough performance wise to be practical for my purposes.