Skip to content

Instantly share code, notes, and snippets.

@jgpc42
Created August 18, 2017 02:35
Show Gist options
  • Save jgpc42/97fdcf12d4a2977e15b23001f0a612db to your computer and use it in GitHub Desktop.
Save jgpc42/97fdcf12d4a2977e15b23001f0a612db to your computer and use it in GitHub Desktop.
Clojure integer array hashcode benchmark
;; $ java -cp ~/.lein/self-installs/leiningen-2.7.1-standalone.jar clojure.main hashcode-bench.clj
(println "Java" (System/getProperty "java.version"))
(println "Clojure" (apply str ((juxt :major (constantly \.) :minor) *clojure-version*)))
;; => Java 1.8.0_131
;; => Clojure 1.8
(require '[cemerick.pomegranate :as pom])
(pom/add-dependencies
:coordinates '[[criterium "0.4.4"]
[insn "0.1.0"]]
:repositories {"clojars" "https://clojars.org/repo"})
(require '[criterium.core :as crit]
'[insn.clojure :as bc])
(import [java.util Arrays])
(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)
(bc/defn bytecode ^long [arr]
[[:aload 1] [:ifnull :L/NULL] ;; if arr == null then goto NULL
[:aload 1] [:checkcast [:int]] [:astore 1] ;; arr = (int[]) arr
[:aload 1] [:arraylength] [:istore 2] ;; len = arr.length
[:ldc 0] [:istore 3] ;; i = 0
[:ldc 1] [:istore 4] ;; h = 1
[:mark :L/LOOP]
[:iload 2] [:iload 3] [:if-icmpeq :L/RET] ;; if len == i then goto RET
[:ldc 31] [:iload 4] [:imul] ;; push h * 31
[:aload 1] [:iload 3] [:iaload] ;; push arr[i]
[:iadd] [:istore 4] ;; add pushed values, store into h
[:iinc 3 1] [:goto :L/LOOP] ;; i++, goto LOOP
[:mark :L/RET]
[:iload 4] [:i2l] [:lreturn] ;; return h as long
[:mark :L/NULL]
[:ldc2 0] [:lreturn]]) ;; return 0L
(defn clojure ^long [^ints arr]
(if (nil? arr)
0
(let [len (long (alength arr))]
(loop [i 0, h 1]
(if (< i len)
(recur (unchecked-inc i)
(unchecked-add-int
(unchecked-multiply-int
(unchecked-int h) (unchecked-int 31))
(aget arr (unchecked-int i))))
h)))))
(defn java ^long [^ints arr]
(Arrays/hashCode arr))
(let [array (int-array (range 100))
exp (java array)]
(crit/bench (assert (== exp (bytecode array)))) ;; => Execution time mean : 89.884445 ns
(crit/bench (assert (== exp (clojure array)))) ;; => Execution time mean : 125.551577 ns
(crit/bench (assert (== exp (java array))))) ;; => Execution time mean : 89.781852 ns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment