Skip to content

Instantly share code, notes, and snippets.

@xificurC
Last active December 18, 2018 13:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xificurC/df079feb85bb118efd305764c8714cf5 to your computer and use it in GitHub Desktop.
Save xificurC/df079feb85bb118efd305764c8714cf5 to your computer and use it in GitHub Desktop.
Clojure specter benchmarks done with criterium benchmarking library
Leiningen 2.8.1 on Java 1.8.0_181 OpenJDK 64-Bit Server VM
{:dependencies
([org.clojure/clojure "1.9.0"] [criterium/criterium "0.4.4"]),
:jvm-opts nil,
:eval-in nil}
Benchmark: get value in nested map
Mean(us) vs best Code
0.0220 1.00 (-> data (get :a) (get :b) (get :c))
0.0332 1.51 (-> data :a :b :c)
0.0340 1.55 (-> data :a :b :c identity)
0.0359 1.63 (get-a-b-c data)
0.0612 2.78 (compiled-select-any p data)
0.0658 2.99 (select-any [(keypath :a) (keypath :b) (keypath :c)] data)
0.0660 3.00 (select-any [:a :b :c] data)
0.0730 3.32 (select-one [:a :b :c] data)
0.0845 3.84 (get-in data [:a :b :c])
0.112 5.09 (select-any (keypath :a :b :c) data)
0.120 5.47 (select-one! [:a :b :c] data)
0.123 5.57 (select-first [:a :b :c] data)
0.129 5.87 (specter-dynamic-nested-get data :a :b :c)
********************************
Benchmark: set value in nested map
Mean(us) vs best Code
0.177 1.00 (setval [:a :b :c] 1 data)
0.204 1.16 (assoc-in data [:a :b :c] 1)
********************************
Benchmark: update value in nested map
Mean(us) vs best Code
0.206 1.00 (manual-transform data inc)
0.229 1.11 (transform [:a :b :c] inc data)
0.325 1.58 (update-in data [:a :b :c] inc)
********************************
Benchmark: transform values of a list
Mean(us) vs best Code
0.648 1.00 (doall (sequence (map inc) data))
0.807 1.24 (transform ALL inc data)
0.994 1.53 (reverse (into (quote ()) (map inc) data))
********************************
Benchmark: transform values of a small map
Mean(us) vs best Code
0.169 1.00 (transform MAP-VALS inc data)
0.189 1.12 (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
0.204 1.21 (map-vals-map-iterable data inc)
0.215 1.27 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
0.295 1.74 (map-vals-map-iterable-transient data inc)
0.297 1.76 (reduce-kv (fn [m k v] (assoc m k (inc v))) (empty data) data)
0.499 2.95 (into {} (map (fn [e] [(key e) (inc (val e))])) data)
0.911 5.39 (transform [ALL LAST] inc data)
1.23 7.25 (zipmap (keys data) (map inc (vals data)))
1.38 8.16 (into {} (for [[k v] data] [k (inc v)]))
1.39 8.23 (into {} (map (fn [e] [(key e) (inc (val e))]) data))
********************************
Benchmark: transform values of large map
Mean(us) vs best Code
185 1.00 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient clojure.lang.PersistentHashMap/EMPTY) data))
190 1.03 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
194 1.05 (transform MAP-VALS inc data)
229 1.24 (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
248 1.34 (reduce-kv (fn [m k v] (assoc m k (inc v))) (empty data) data)
296 1.60 (into {} (map (fn [e] [(key e) (inc (val e))])) data)
322 1.74 (map-vals-map-iterable-transient data inc)
357 1.93 (map-vals-map-iterable data inc)
381 2.06 (transform [ALL LAST] inc data)
473 2.56 (into {} (for [[k v] data] [k (inc v)]))
479 2.59 (into {} (map (fn [e] [(key e) (inc (val e))]) data))
534 2.88 (zipmap (keys data) (map inc (vals data)))
********************************
Benchmark: first value of a size 10 vector
Mean(us) vs best Code
0.0415 1.00 (select-any ALL data)
0.0415 1.00 (select-first ALL data)
0.0562 1.35 (select-any FIRST data)
0.0705 1.70 (first data)
********************************
Benchmark: map a function over a vector
Mean(us) vs best Code
0.214 1.00 (mapv inc data)
0.398 1.86 (into [] (map inc) data)
0.478 2.24 (transform ALL inc data)
0.664 3.11 (vec (map inc data))
********************************
Benchmark: filter a sequence
Mean(us) vs best Code
0.235 1.00 (filterv even? data)
0.364 1.55 (into [] (filter even?) data)
0.463 1.97 (select [ALL even?] data)
0.490 2.08 (doall (filter even? data))
0.710 3.01 (select-any (filterer even?) data)
********************************
Benchmark: even :a values from sequence of maps
Mean(us) vs best Code
0.385 1.00 (select [ALL :a even?] data)
0.532 1.38 (into [] xf data)
0.545 1.41 (into [] (comp (map :a) (filter even?)) data)
0.732 1.90 (->> data (mapv :a) (filter even?) doall)
********************************
Benchmark: Append to a large vector
Mean(us) vs best Code
0.0397 1.00 (conj v 1)
0.0573 1.44 (reduce conj v [1])
0.0684 1.72 (setval AFTER-ELEM 1 v)
0.196 4.94 (setval END [1] v)
********************************
Benchmark: prepend to a vector
Mean(us) vs best Code
0.490 1.00 (into [0] data)
0.629 1.28 (vec (cons 0 data))
0.641 1.31 (setval BEFORE-ELEM 0 data)
********************************
Benchmark: update every value in a tree (represented with vectors)
Mean(us) vs best Code
1.90 1.00 (tree-value-transform (fn [e] (if (even? e) (inc e) e)) data)
2.78 1.46 (transform [TreeValuesProt even?] inc data)
3.25 1.71 (transform [TreeValues even?] inc data)
3.39 1.78 (transform [(walker number?) even?] inc data)
7.23 3.80 (walk/postwalk (fn [e] (if (and (number? e) (even? e)) (inc e) e)) data)
********************************
Benchmark: transient comparison: building up vectors
Mean(us) vs best Code
19.1 1.00 (reduce (fn [v i] (conj! v i)) (transient []) toappend)
29.1 1.52 (setval END! toappend (transient []))
43.0 2.25 (setval END toappend [])
45.2 2.37 (reduce (fn [v i] (conj v i)) [] toappend)
********************************
Benchmark: transient comparison: building up vectors one at a time
Mean(us) vs best Code
21.3 1.00 (reduce (fn [v i] (conj! v i)) (transient []) toappend)
45.2 2.12 (reduce (fn [v i] (conj v i)) [] toappend)
105 4.95 (reduce (fn [v i] (setval END! [i] v)) (transient []) toappend)
240 11.3 (reduce (fn [v i] (setval END [i] v)) [] toappend)
********************************
Benchmark: transient comparison: assoc'ing in vectors
Mean(us) vs best Code
0.0296 1.00 (assoc! tdata 600 0)
0.0740 2.50 (assoc data 600 0)
0.140 4.72 (setval (keypath! 600) 0 tdata2)
0.192 6.47 (setval (keypath 600) 0 data)
********************************
Benchmark: transient comparison: assoc'ing in maps
Mean(us) vs best Code
0.0880 1.00 (assoc! tdata 600 0)
0.151 1.72 (assoc data 600 0)
0.262 2.98 (setval (keypath! 600) 0 tdata2)
0.346 3.93 (setval (keypath 600) 0 data)
********************************
Benchmark: transient comparison: submap
Mean(us) vs best Code
1.50 1.00 (transform (submap! [600 700]) modify-submap tdata)
2.25 1.50 (transform (submap [600 700]) modify-submap data)
********************************
Benchmark: set metadata
Mean(us) vs best Code
0.0735 1.00 (with-meta data meta-map)
0.164 2.23 (setval META meta-map data)
********************************
Benchmark: get metadata
Mean(us) vs best Code
0.00959 1.00 (meta data)
0.0322 3.36 (select-any META data)
********************************
Benchmark: vary metadata
Mean(us) vs best Code
0.293 1.00 (setval [META :y] 2 data)
0.572 1.95 (vary-meta data assoc :y 2)
********************************
Benchmark: Traverse into a set
Mean(us) vs best Code
190 1.00 (set data)
199 1.05 (persistent! (reduce conj! (transient #{}) (traverse ALL data)))
200 1.05 (into #{} (traverse ALL data))
232 1.22 (set (select ALL data))
302 1.59 (reduce conj #{} (traverse ALL data))
********************************
Benchmark: multi-transform vs. consecutive transforms, one shared nav
Mean(us) vs best Code
1.40 1.00 (multi-transform [ALL (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)
2.04 1.46 (->> data (transform [ALL even?] mult-10) (transform [ALL odd?] dec))
********************************
Benchmark: multi-transform vs. consecutive transforms, three shared navs
Mean(us) vs best Code
5.24 1.00 (multi-transform [ALL ALL number? (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)
7.36 1.41 (->> data (transform [ALL ALL number? even?] mult-10) (transform [ALL ALL number? odd?] dec))
********************************
Benchmark: namespace qualify keys of a small map
Mean(us) vs best Code
0.379 1.00 (setval [MAP-KEYS NAMESPACE] (str *ns*) data)
0.578 1.53 (reduce-kv (fn [m k v] (assoc m (keyword (str *ns*) (name k)) v)) {} data)
1.24 3.27 (into {} (map (fn [[k v]] [(keyword (str *ns*) (name k)) v])) data)
********************************
Benchmark: namespace qualify keys of a large map
Mean(us) vs best Code
321 1.00 (setval [MAP-KEYS NAMESPACE] (str *ns*) data)
488 1.52 (into {} (map (fn [[k v]] [(keyword (str *ns*) (name k)) v])) data)
508 1.58 (reduce-kv (fn [m k v] (assoc m (keyword (str *ns*) (name k)) v)) {} data)
********************************
Benchmark: walker vs. clojure.walk version
Mean(us) vs best Code
8.49 1.00 (transform (walker number?) inc data)
13.3 1.56 (transform (walker-old number?) inc data)
********************************
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment