Skip to content

Instantly share code, notes, and snippets.

@lambder
Forked from stuartsierra/sum.clj
Created August 24, 2013 23:25
Show Gist options
  • Save lambder/6330993 to your computer and use it in GitHub Desktop.
Save lambder/6330993 to your computer and use it in GitHub Desktop.
;; Demonstration of JVM dead code elimination in Clojure 1.2 and 1.5
;;
;; This Clojure script demonstrates some of the effects of dead code
;; elimination in the JVM. For unknown reasons, the bytecode produced
;; by Clojure 1.2.1 is more susceptible to elimination than the
;; bytecode produced by Clojure 1.5.1, making it seem like 1.2.1 is
;; faster. But when the code is forced to do real work, the difference
;; disappears.
;;
;; My results with Clojure 1.2.1:
;;
;; Dead code:
;; Computed 10000.0 in 133 msecs
;; Computed 10000.0 in 108 msecs
;; Computed 10000.0 in 50 msecs
;; Computed 10000.0 in 15 msecs
;; Computed 10000.0 in 15 msecs
;; Live code:
;; Computed 4.9995E11 in 96 msecs
;; Computed 4.9995E11 in 97 msecs
;; Computed 4.9995E11 in 93 msecs
;; Computed 4.9995E11 in 94 msecs
;; Computed 4.9995E11 in 96 msecs
;;
;; My results with Clojure 1.5.1:
;;
;; Dead code:
;; Computed 10000.0 in 256 msecs
;; Computed 10000.0 in 122 msecs
;; Computed 10000.0 in 114 msecs
;; Computed 10000.0 in 94 msecs
;; Computed 10000.0 in 97 msecs
;; Live code:
;; Computed 4.9995E11 in 96 msecs
;; Computed 4.9995E11 in 95 msecs
;; Computed 4.9995E11 in 97 msecs
;; Computed 4.9995E11 in 93 msecs
;; Computed 4.9995E11 in 94 msecs
;;; Code for Clojure 1.5.1:
(set! *unchecked-math* true)
(defn sum ^double [^doubles array]
(loop [total 0.0
i 0]
(if (< i (alength array))
(recur (+ total (aget array i)) (unchecked-inc i))
total)))
;;; Alternate version for Clojure 1.2.1:
;;
;; (defn sum [^"[D" array]
;; (loop [total (double 0.0)
;; i (int 0)]
;; (if (< i (alength array))
;; (recur (+ total (aget array i)) (unchecked-inc i))
;; total)))
;;; Benchmark:
(defn build-array []
(let [array (double-array 10000)]
(dotimes [i 10000]
(aset array i (double i)))
array))
(def array (build-array))
(println "Dead code:")
(dotimes [_ 5]
(let [start (System/currentTimeMillis)
grand-total (loop [grand-total 0.0
i 0]
(if (< i 10000)
(do (sum array)
(recur (+ grand-total 1.0) (inc i)))
grand-total))
stop (System/currentTimeMillis)]
(println "Computed" grand-total "in" (- stop start) "msecs")))
(println "Live code:")
(dotimes [_ 5]
(let [start (System/currentTimeMillis)
grand-total (loop [grand-total 0.0
i 0]
(if (< i 10000)
(recur (+ grand-total (sum array)) (inc i))
grand-total))
stop (System/currentTimeMillis)]
(println "Computed" grand-total "in" (- stop start) "msecs")))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment