ClojureScript micro benchmarks over different releases
Setup
These benchmarks were run on Mint Linux with the following engines:
- Javascript Core (JSC): Bundled with WebKit as of 2017-05-24
- V8 (V8): v6.1.0 (candidate)
- SpiderMonkey (SM): JavaScript-C55.0a1
The code for running these benchmarks is here.
File Size
Benchmarks
identity
- [x 1] (identity x)
symbol construction
- [] (symbol (quote foo))
array-reduce & ci-reduce
- [coll (seq arr)] (ci-reduce coll + 0)
- [coll (seq arr)] (ci-reduce coll sum 0)
- [coll arr] (array-reduce coll + 0)
- [coll arr] (array-reduce coll sum 0)
instance?
- [coll []] (instance? PersistentVector coll)
satisfies?
- [coll (list 1 2 3)] (satisfies? ISeq coll)
- [coll [1 2 3]] (satisfies? ISeq coll)
array & string ops
- [coll (array 1 2 3)] (seq coll)
- [coll "foobar"] (seq coll)
- [coll (array 1 2 3)] (first coll)
- [coll "foobar"] (first coll)
- [coll (array 1 2 3)] (nth coll 2)
- [coll "foobar"] (nth coll 2)
cloning & specify
- [coll [1 2 3]] (clone coll)
- [coll [1 2 3]] (specify coll IFoo (foo [_] :bar))
- [coll (specify [1 2 3] IFoo (foo [_] :bar))] (foo coll)
list ops
- [coll (list 1 2 3)] (first coll)
- [coll (list 1 2 3)] (-first coll)
- [coll (list 1 2 3)] (rest coll)
- [coll (list 1 2 3)] (-rest coll)
- [] (list)
- [] (list 1 2 3)
vector ops
- [] []
- [[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count [a b c])
- [[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count (vec (array a b c)))
- [[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count (vector a b c))
- [coll [1 2 3]] (transient coll)
- [coll [1 2 3]] (nth coll 0)
- [coll [1 2 3]] (-nth coll 0)
- [coll [1 2 3]] (-nth coll 0)
- [coll [1 2 3]] (coll 0)
- [coll [1 2 3]] (conj coll 4)
- [coll [1 2 3]] (-conj coll 4)
- [coll []] (-conj coll 1)
- [coll [1]] (-conj coll 2)
- [coll [1 2]] (-conj coll 3)
- [coll [1 2 3]] (seq coll)
- [coll [1 2 3]] (-seq coll)
- [coll (seq [1 2 3])] (first coll)
- [coll (seq [1 2 3])] (-first coll)
- [coll (seq [1 2 3])] (rest coll)
- [coll (seq [1 2 3])] (-rest coll)
- [coll (seq [1 2 3])] (next coll)
large vector ops
- [] (reduce conj [] (range 40000))
- [coll (reduce conj [] (range (+ 32768 32)))] (conj coll :foo)
- [coll (reduce conj [] (range 40000))] (assoc coll 123 :foo)
- [coll (reduce conj [] (range (+ 32768 33)))] (pop coll)
chunked seqs
- [] (-first v)
- [] (-next v)
- [] (-rest v)
transient vector, conj! 1000000 items
- [v []] (loop [i 0 v (transient v)] (if (> i 1000000) (persistent! v) (recur (inc i) (conj! v i))))
vector equality
- [a (into [] (range 100000)) b (into [] (range 100000))] (= a b)
keyword compare
- [arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))] (.sort arr compare)
- [arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))] (.sort arr compare)
reduce lazy-seqs, vectors, ranges
- [coll (take 100000 (iterate inc 0))] (reduce + 0 coll)
- [coll (range 100000)] (reduce + 0 coll)
- [coll (into [] (range 100000))] (reduce + 0 coll)
apply
- [coll (into [] (range 100000))] (apply + coll)
- [] (list 1 2 3 4 5)
- [xs (array-seq (array 1 2 3 4 5))] (apply list xs)
- [xs (list 1 2 3 4 5)] (apply list xs)
- [xs [1 2 3 4 5]] (apply list xs)
- [f (fn [a b & more])] (apply f (range 32))
- [f (fn [a b c d e f g h i j & more])] (apply f (range 32))
update-in
- [coll {:foo 1} ks [:foo]] (update-in coll ks inc)
- [coll (array-map :foo 1) ks [:foo]] (update-in coll ks inc)
obj-map
- [coll (obj-map)] (assoc coll :foo :bar)
- [coll (obj-map :foo :bar)] (-lookup coll :foo)
- [coll (obj-map :foo :bar)] (assoc coll :baz :woz)
- [coll (obj-map :foo :bar :baz :woz)] (-lookup coll :baz)
- [coll (obj-map :foo :bar :baz :woz :lol :rofl)] (-lookup coll :lol)
array-map
- [] {[1] true, [2] true, [3] true}
- [coll (array-map)] (assoc coll :foo :bar)
- [coll (array-map :foo :bar)] (-lookup coll :foo)
- [coll (array-map :foo :bar)] (assoc coll :baz :woz)
- [coll (array-map :foo :bar :baz :woz)] (-lookup coll :baz)
- [coll (array-map :foo :bar :baz :woz :lol :rofl)] (-lookup coll :lol)
array-map w/ symbols
- [coll (array-map)] (assoc coll a b)
- [coll (array-map a b)] (-lookup coll a)
- [coll (array-map a b)] (assoc coll c d)
- [coll (array-map a b c d)] (-lookup coll c)
- [coll (array-map a b c d e f)] (-lookup coll e)
array-map w/ inline symbols
- [coll (array-map)] (assoc coll (quote foo) (quote bar))
- [coll (array-map (quote foo) (quote bar))] (-lookup coll (quote foo))
- [coll (array-map (quote foo) (quote bar))] (assoc coll (quote baz) (quote woz))
- [coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))] (-lookup coll (quote baz))
- [coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))] (-lookup coll (quote lol))
map / record ops
- [coll {:foo 1, :bar 2}] (get coll :foo)
- [coll {(quote foo) 1, (quote bar) 2}] (get coll (quote foo))
- [coll {:foo 1, :bar 2}] (-lookup coll :foo nil)
- [coll {(quote foo) 1, (quote bar) 2}] (-lookup coll (quote foo) nil)
- [coll {:foo 1, :bar 2}] (:foo coll)
- [coll {(quote foo) 1, (quote bar) 2}] ((quote foo) coll)
- [coll {:foo 1, :bar 2}] (kw coll)
- [coll {(quote foo) 1, (quote bar) 2}] (sym coll)
- [coll {:foo 1, :bar 2}] (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m))
- [coll (Foo. 1 2)] (:bar coll)
- [coll (Foo. 1 2)] (-lookup coll :bar)
- [coll (Foo. 1 2)] (assoc coll :bar 2)
- [coll (Foo. 1 2)] (assoc coll :baz 3)
- [coll (Foo. 1 2)] (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m))
zipmap
- [m {:a 1, :b 2, :c 3}] (zipmap (keys m) (map inc (vals m)))
persistent hash maps
- [key :f0] (hash key)
- [key "f0"] (m3-hash-unencoded-chars key)
- [key :unsynchronized-mutable] (hash key)
- [coll hash-coll-test] (hash-coll coll)
- [coll hash-coll-test] (hash-ordered-coll coll)
- [coll hash-imap-test] (hash-imap coll)
- [coll hash-imap-test] (hash-unordered-coll coll)
- [coll pmap] (:f0 coll)
- [coll pmap] (get coll :f0)
- [coll pmap] (-lookup coll :f0 nil)
- [coll pmap] (-lookup hash-imap-test :foo500 nil)
- [coll pmap] (-lookup hash-imap-int-test 500 nil)
- [coll pmap] (assoc coll :g0 32)
- [coll pmap] (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m))
- [coll cljs.core.PersistentHashMap.EMPTY] (assoc coll :f0 1)
transient map, conj! 100000 items
- [m cljs.core.PersistentHashMap.EMPTY] (loop [i 0 m (transient m)] (if (> i 100000) (persistent! m) (recur (inc i) (assoc! m i i))))
set ops
- [] #{}
- [] #{1 3 2}
- [v [1 2 3]] (set v)
- [] (hash-set 1 2 3)
- [coll #{1 3 2}] (conj coll 4)
- [coll #{1 3 2}] (get coll 2)
- [coll #{1 3 2}] (contains? coll 2)
- [coll #{1 3 2}] (coll 2)
seq ops
- [coll (range 500000)] (reduce + coll)
reader
- [s "{:foo [1 2 3]}"] (reader/read-string s)
- [s big-str-data] (reader/read-string s)
range
- [r (range 100000)] (last r)
lazy-seq - first run
- [r r] (last r)
lazy-seq - second run
- [r r] (last r)
Sequence iterator
- [s (seq ipmap)] (let [iter (seq-iter s)] (loop [v nil] (if (.hasNext iter) (recur (.next iter)) v)))
comprehensions
- [xs (range 512)] (last (for [x xs y xs] (+ x y)))
- [xs (vec (range 512))] (last (for [x xs y xs] (+ x y)))
- [a (Box. 0) xs (range 512)] (doseq [x xs y xs] (set! a -val (+ (.-val a) x)))
- [a (Box. 0) xs (vec (range 512))] (doseq [x xs y xs] (set! a -val (+ (.-val a) x)))
reducers
- [xs (into [] (range 100000))] (r/reduce + (r/map inc (r/map inc (r/map inc xs))))
transducers
- [xs (into [] (range 100000))] (transduce (comp (map inc) (map inc) (map inc)) + 0 xs)
primitive array reduce 1000000 many ops
- [xs (into-array (range 100000))] (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0))
reduce range 100000 many ops
- [xs (range 100000)] (reduce + 0 (map inc (map inc (map inc xs))))
transduce range 100000 many ops
- [xs (range 100000)] (transduce (comp (map inc) (map inc) (map inc)) + 0 xs)
multimethods
- [] (simple-multi :foo)
higher-order variadic function calls
- [f array] (f 1 2 3 4 5 6 7 8 9 0)
- [f vector] (f 1 2 3 4 5 6 7 8 9 0)
- [] (= 1 1 1 1 1 1 1 1 1 0)
Destructuring a sequence
- [v (into [] (range 100000))] (loop [[x & xs] v] (if-not (nil? xs) (recur xs) x))
String macro
- [] (str 1)
- [] (str nil)
- [] (str "1")
- [] (str "1" "2")
- [] (str "1" "2" "3")
Charts
[] (symbol (quote foo))
Top
[coll (seq arr)] (ci-reduce coll + 0)
Top
[coll (seq arr)] (ci-reduce coll sum 0)
Top
[coll arr] (array-reduce coll + 0)
Top
[coll arr] (array-reduce coll sum 0)
Top
[coll []] (instance? PersistentVector coll)
Top
[coll (list 1 2 3)] (satisfies? ISeq coll)
Top
[coll [1 2 3]] (satisfies? ISeq coll)
Top
[coll (array 1 2 3)] (seq coll)
Top
[coll "foobar"] (seq coll)
Top
[coll (array 1 2 3)] (first coll)
Top
[coll "foobar"] (first coll)
Top
[coll (array 1 2 3)] (nth coll 2)
Top
[coll "foobar"] (nth coll 2)
Top
[coll [1 2 3]] (clone coll)
Top
[coll [1 2 3]] (specify coll IFoo (foo [_] :bar))
Top
[coll (specify [1 2 3] IFoo (foo [_] :bar))] (foo coll)
Top
[coll (list 1 2 3)] (first coll)
Top
[coll (list 1 2 3)] (-first coll)
Top
[coll (list 1 2 3)] (rest coll)
Top
[coll (list 1 2 3)] (-rest coll)
Top
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count [a b c])
Top
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count (vec (array a b c)))
Top
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))] (-count (vector a b c))
Top
[coll [1 2 3]] (transient coll)
Top
[coll [1 2 3]] (nth coll 0)
Top
[coll [1 2 3]] (-nth coll 0)
Top
[coll [1 2 3]] (-nth coll 0)
Top
[coll [1 2 3]] (coll 0)
Top
[coll [1 2 3]] (conj coll 4)
Top
[coll [1 2 3]] (-conj coll 4)
Top
[coll []] (-conj coll 1)
Top
[coll [1]] (-conj coll 2)
Top
[coll [1 2]] (-conj coll 3)
Top
[coll [1 2 3]] (seq coll)
Top
[coll [1 2 3]] (-seq coll)
Top
[coll (seq [1 2 3])] (first coll)
Top
[coll (seq [1 2 3])] (-first coll)
Top
[coll (seq [1 2 3])] (rest coll)
Top
[coll (seq [1 2 3])] (-rest coll)
Top
[coll (seq [1 2 3])] (next coll)
Top
[] (reduce conj [] (range 40000))
Top
[coll (reduce conj [] (range (+ 32768 32)))] (conj coll :foo)
Top
[coll (reduce conj [] (range 40000))] (assoc coll 123 :foo)
Top
[coll (reduce conj [] (range (+ 32768 33)))] (pop coll)
Top
[v []] (loop [i 0 v (transient v)] (if (> i 1000000) (persistent! v) (recur (inc i) (conj! v i))))
Top
[a (into [] (range 100000)) b (into [] (range 100000))] (= a b)
Top
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))] (.sort arr compare)
Top
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))] (.sort arr compare)
Top
[coll (take 100000 (iterate inc 0))] (reduce + 0 coll)
Top
[coll (range 100000)] (reduce + 0 coll)
Top
[coll (into [] (range 100000))] (reduce + 0 coll)
Top
[coll (into [] (range 100000))] (apply + coll)
Top
[xs (array-seq (array 1 2 3 4 5))] (apply list xs)
Top
[xs (list 1 2 3 4 5)] (apply list xs)
Top
[xs [1 2 3 4 5]] (apply list xs)
Top
[f (fn [a b & more])] (apply f (range 32))
Top
[f (fn [a b c d e f g h i j & more])] (apply f (range 32))
Top
[coll {:foo 1} ks [:foo]] (update-in coll ks inc)
Top
[coll (array-map :foo 1) ks [:foo]] (update-in coll ks inc)
Top
[coll (obj-map)] (assoc coll :foo :bar)
Top
[coll (obj-map :foo :bar)] (-lookup coll :foo)
Top
[coll (obj-map :foo :bar)] (assoc coll :baz :woz)
Top
[coll (obj-map :foo :bar :baz :woz)] (-lookup coll :baz)
Top
[coll (obj-map :foo :bar :baz :woz :lol :rofl)] (-lookup coll :lol)
Top
[] {[1] true, [2] true, [3] true}
Top
[coll (array-map)] (assoc coll :foo :bar)
Top
[coll (array-map :foo :bar)] (-lookup coll :foo)
Top
[coll (array-map :foo :bar)] (assoc coll :baz :woz)
Top
[coll (array-map :foo :bar :baz :woz)] (-lookup coll :baz)
Top
[coll (array-map :foo :bar :baz :woz :lol :rofl)] (-lookup coll :lol)
Top
[coll (array-map)] (assoc coll a b)
Top
[coll (array-map a b)] (-lookup coll a)
Top
[coll (array-map a b)] (assoc coll c d)
Top
[coll (array-map a b c d)] (-lookup coll c)
Top
[coll (array-map a b c d e f)] (-lookup coll e)
Top
[coll (array-map)] (assoc coll (quote foo) (quote bar))
Top
[coll (array-map (quote foo) (quote bar))] (-lookup coll (quote foo))
Top
[coll (array-map (quote foo) (quote bar))] (assoc coll (quote baz) (quote woz))
Top
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))] (-lookup coll (quote baz))
Top
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))] (-lookup coll (quote lol))
Top
[coll {:foo 1, :bar 2}] (get coll :foo)
Top
[coll {(quote foo) 1, (quote bar) 2}] (get coll (quote foo))
Top
[coll {:foo 1, :bar 2}] (-lookup coll :foo nil)
Top
[coll {(quote foo) 1, (quote bar) 2}] (-lookup coll (quote foo) nil)
Top
[coll {:foo 1, :bar 2}] (:foo coll)
Top
[coll {(quote foo) 1, (quote bar) 2}] ((quote foo) coll)
Top
[coll {:foo 1, :bar 2}] (kw coll)
Top
[coll {(quote foo) 1, (quote bar) 2}] (sym coll)
Top
[coll {:foo 1, :bar 2}] (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m))
Top
[coll (Foo. 1 2)] (:bar coll)
Top
[coll (Foo. 1 2)] (-lookup coll :bar)
Top
[coll (Foo. 1 2)] (assoc coll :bar 2)
Top
[coll (Foo. 1 2)] (assoc coll :baz 3)
Top
[coll (Foo. 1 2)] (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m))
Top
[m {:a 1, :b 2, :c 3}] (zipmap (keys m) (map inc (vals m)))
Top
[key "f0"] (m3-hash-unencoded-chars key)
Top
[key :unsynchronized-mutable] (hash key)
Top
[coll hash-coll-test] (hash-coll coll)
Top
[coll hash-coll-test] (hash-ordered-coll coll)
Top
[coll hash-imap-test] (hash-imap coll)
Top
[coll hash-imap-test] (hash-unordered-coll coll)
Top
[coll pmap] (:f0 coll)
Top
[coll pmap] (get coll :f0)
Top
[coll pmap] (-lookup coll :f0 nil)
Top
[coll pmap] (-lookup hash-imap-test :foo500 nil)
Top
[coll pmap] (-lookup hash-imap-int-test 500 nil)
Top
[coll pmap] (assoc coll :g0 32)
Top
[coll pmap] (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m))
Top
[coll cljs.core.PersistentHashMap.EMPTY] (assoc coll :f0 1)
Top
[m cljs.core.PersistentHashMap.EMPTY] (loop [i 0 m (transient m)] (if (> i 100000) (persistent! m) (recur (inc i) (assoc! m i i))))
Top
[coll #{1 3 2}] (conj coll 4)
Top
[coll #{1 3 2}] (get coll 2)
Top
[coll #{1 3 2}] (contains? coll 2)
Top
[coll #{1 3 2}] (coll 2)
Top
[coll (range 500000)] (reduce + coll)
Top
[s "{:foo [1 2 3]}"] (reader/read-string s)
Top
[s big-str-data] (reader/read-string s)
Top
[r (range 100000)] (last r)
Top
[s (seq ipmap)] (let [iter (seq-iter s)] (loop [v nil] (if (.hasNext iter) (recur (.next iter)) v)))
Top
[xs (range 512)] (last (for [x xs y xs] (+ x y)))
Top
[xs (vec (range 512))] (last (for [x xs y xs] (+ x y)))
Top
[a (Box. 0) xs (range 512)] (doseq [x xs y xs] (set! a -val (+ (.-val a) x)))
Top
[a (Box. 0) xs (vec (range 512))] (doseq [x xs y xs] (set! a -val (+ (.-val a) x)))
Top
[xs (into [] (range 100000))] (r/reduce + (r/map inc (r/map inc (r/map inc xs))))
Top
[xs (into [] (range 100000))] (transduce (comp (map inc) (map inc) (map inc)) + 0 xs)
Top
[xs (into-array (range 100000))] (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0))
Top
[xs (range 100000)] (reduce + 0 (map inc (map inc (map inc xs))))
Top
[xs (range 100000)] (transduce (comp (map inc) (map inc) (map inc)) + 0 xs)
Top
[] (simple-multi :foo)
Top
[f array] (f 1 2 3 4 5 6 7 8 9 0)
Top
[f vector] (f 1 2 3 4 5 6 7 8 9 0)
Top
[] (= 1 1 1 1 1 1 1 1 1 0)
Top
[v (into [] (range 100000))] (loop [[x & xs] v] (if-not (nil? xs) (recur xs) x))
Top