-
-
Save lambder/6330993 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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