Saturday, January 03, 2009

Clojure vs JavaFX Script: only 5x slower!

Chris Oliver compares his JavaFX script to JRuby and Groovy and finds JavaFX 25 times faster.

I failed to get JavaFX compiler running on my Ubuntu, but I easily ran Chris's JRuby 1.1.6 test; so for calibration, my laptop comes in at 3:52, vs 4:22 on Chris's machine. Presumably we can scale results on my machine by 1.13.

Here's my Clojure version of the test:


(defn tak [#^Integer x #^Integer y #^Integer z]
(if (>= y x)
z
(recur (tak (- x 1) y z)
(tak (- y 1) z x)
(tak (- z 1) x y))))

(dotimes [n 1000] (tak 24 16 8))



It runs in about 50 seconds, or 56 after normalizing to Chris' machine speed. This puts Clojure north of JRuby and Groovy, but still 5 times slower than JavaFX.

If you remove the type hints, it runs in 4 minutes, or about the same time as JRuby -- and about 4 or 5 times slower than with type hints.

4 comments:

  1. (defn tak [#^Integer x #^Integer y #^Integer z]
    (if (<= y x)
    z
    (recur
    ((unchecked-dec x) y z)
    ((unchecked-dec y) z x)
    ((unchecked-dec z) x y))))

    (dotimes [n 1000] (tak 24 16 8))

    ReplyDelete
  2. That code is wrong -- the comparison goes the other way -- and when I fixed that and run it, I get ClassCastException.

    ReplyDelete
  3. Anonymous probably meant to say:

    (defn tak [#^Integer x #^Integer y #^Integer z]
    (if (>= y x)
    z
    (recur (tak (unchecked-dec x) y z)
    (tak (unchecked-dec y) z x)
    (tak (unchecked-dec z) x y))))

    ReplyDelete
  4. With Clojure 1.3 it is much faster then original if you use:
    (defn ^long tak [^long x ^long y ^long z]
    (if (>= y x)
    z
    (recur (long (tak (- x 1) y z))
    (long (tak (- y 1) z x))
    (long (tak (- z 1) x y)))))

    ReplyDelete