new benchmark cases, reduce benchmark iterations

This commit is contained in:
Nathan Marz 2016-06-17 12:56:33 -04:00
parent 4c9c4b0001
commit d0331c9afe
2 changed files with 23 additions and 16 deletions

View file

@ -1,6 +1,6 @@
## 0.12.0 (unreleased) ## 0.12.0 (unreleased)
* BREAKING CHANGE: Changed semantics of `Navigator` protocol `select*` in order to enable very large performance improvements to `select`, `select-one`, `select-first`, and `select-one!`. Custom navigators will need to be updated to comform to the new required semantics. Codebases that do not use custom navigators do not require any changes. See the docstring on the protocol for the details. * BREAKING CHANGE: Changed semantics of `Navigator` protocol `select*` in order to enable very large performance improvements to `select`, `select-one`, `select-first`, and `select-one!`. Custom navigators will need to be updated to conform to the new required semantics. Codebases that do not use custom navigators do not require any changes. See the docstring on the protocol for the details.
* Added `select-any` operation which selects a single element navigated to by the path. Which element returned is undefined. If no elements are navigated to, returns `com.rpl.specter/NONE`. This is the fastest selection operation. * Added `select-any` operation which selects a single element navigated to by the path. Which element returned is undefined. If no elements are navigated to, returns `com.rpl.specter/NONE`. This is the fastest selection operation.
* Added `selected-any?` operation that returns true if any element is navigated to. * Added `selected-any?` operation that returns true if any element is navigated to.
* Added `traverse` operation which returns a reducible object of all the elements navigated to by the path. Very efficient. * Added `traverse` operation which returns a reducible object of all the elements navigated to by the path. Very efficient.

View file

@ -3,10 +3,12 @@
[com.rpl.specter macros] [com.rpl.specter macros]
[com.rpl.specter.transients] [com.rpl.specter.transients]
[com.rpl.specter.impl :only [benchmark]]) [com.rpl.specter.impl :only [benchmark]])
(:require [clojure.walk :as walk])) (:require [clojure.walk :as walk])
)
;; run via `lein repl` with `(load-file "scripts/benchmarks.clj")` ;; run via `lein repl` with `(load-file "scripts/benchmarks.clj")`
(defn pretty-float5 [anum] (defn pretty-float5 [anum]
(format "%.5g" anum)) (format "%.5g" anum))
@ -33,6 +35,8 @@
(time-ms amt-per-iter afn))))) (time-ms amt-per-iter afn)))))
(defn compare-benchmark [amt-per-iter afn-map] (defn compare-benchmark [amt-per-iter afn-map]
(System/runFinalization)
(System/gc)
(let [results (transform MAP-VALS (let [results (transform MAP-VALS
(fn [afn] (fn [afn]
(average-time-ms 8 amt-per-iter afn)) (average-time-ms 8 amt-per-iter afn))
@ -54,7 +58,7 @@
(let [data {:a {:b {:c 1}}} (let [data {:a {:b {:c 1}}}
p (comp-paths :a :b :c)] p (comp-paths :a :b :c)]
(run-benchmark "get value in nested map" 5000000 (run-benchmark "get value in nested map" 2500000
(select-any [:a :b :c] data) (select-any [:a :b :c] data)
(select-one [:a :b :c] data) (select-one [:a :b :c] data)
(select-first [:a :b :c] data) (select-first [:a :b :c] data)
@ -110,7 +114,7 @@
))))) )))))
(let [data {:a 1 :b 2 :c 3 :d 4}] (let [data {:a 1 :b 2 :c 3 :d 4}]
(run-benchmark "transform values of a small map" 1000000 (run-benchmark "transform values of a small map" 500000
(into {} (for [[k v] data] [k (inc v)])) (into {} (for [[k v] data] [k (inc v)]))
(reduce-kv (fn [m k v] (assoc m k (inc v))) {} data) (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
(persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data)) (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
@ -124,7 +128,7 @@
)) ))
(let [data (->> (for [i (range 1000)] [i i]) (into {}))] (let [data (->> (for [i (range 1000)] [i i]) (into {}))]
(run-benchmark "transform values of large map" 1000 (run-benchmark "transform values of large map" 600
(into {} (for [[k v] data] [k (inc v)])) (into {} (for [[k v] data] [k (inc v)]))
(reduce-kv (fn [m k v] (assoc m k (inc v))) {} data) (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
(persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data)) (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
@ -146,22 +150,25 @@
)) ))
(let [data [1 2 3 4 5 6 7 8 9 10]] (let [data [1 2 3 4 5 6 7 8 9 10]]
(run-benchmark "filter a sequence" 1000000 (run-benchmark "filter a sequence" 500000
(doall (filter even? data)) (doall (filter even? data))
(filterv even? data) (filterv even? data)
(select [ALL even?] data) (select [ALL even?] data)
(select-any (filterer even?) data) (select-any (filterer even?) data)
)) ))
(let [data [{:a 2 :b 2} {:a 1} {:a 4} {:a 6}]] (let [data [{:a 2 :b 2} {:a 1} {:a 4} {:a 6}]
(run-benchmark "even :a values from sequence of maps" 1000000 xf (comp (map :a) (filter even?))]
(run-benchmark "even :a values from sequence of maps" 500000
(select [ALL :a even?] data) (select [ALL :a even?] data)
(->> data (mapv :a) (filter even?) doall) (->> data (mapv :a) (filter even?) doall)
(into [] (comp (map :a) (filter even?)) data)
(into [] xf data)
)) ))
(let [v (vec (range 1000))] (let [v (vec (range 1000))]
(run-benchmark "END on large vector" (run-benchmark "END on large vector"
5000000 2000000
(setval END [1] v) (setval END [1] v)
(reduce conj v [1]) (reduce conj v [1])
(conj v 1))) (conj v 1)))
@ -199,7 +206,7 @@
(let [toappend (range 1000)] (let [toappend (range 1000)]
(run-benchmark "transient comparison: building up vectors" (run-benchmark "transient comparison: building up vectors"
10000 8000
(reduce (fn [v i] (conj v i)) [] toappend) (reduce (fn [v i] (conj v i)) [] toappend)
(reduce (fn [v i] (conj! v i)) (transient []) toappend) (reduce (fn [v i] (conj! v i)) (transient []) toappend)
(setval END toappend []) (setval END toappend [])
@ -207,7 +214,7 @@
(let [toappend (range 1000)] (let [toappend (range 1000)]
(run-benchmark "transient comparison: building up vectors one at a time" (run-benchmark "transient comparison: building up vectors one at a time"
10000 7000
(reduce (fn [v i] (conj v i)) [] toappend) (reduce (fn [v i] (conj v i)) [] toappend)
(reduce (fn [v i] (conj! v i)) (transient []) toappend) (reduce (fn [v i] (conj! v i)) (transient []) toappend)
(reduce (fn [v i] (setval END [i] v)) [] toappend) (reduce (fn [v i] (setval END [i] v)) [] toappend)
@ -231,7 +238,7 @@
tdata2 (transient data) tdata2 (transient data)
idx 600] idx 600]
(run-benchmark "transient comparison: assoc'ing in maps" (run-benchmark "transient comparison: assoc'ing in maps"
2500000 1500000
(assoc data idx 0) (assoc data idx 0)
(assoc! tdata idx 0) (assoc! tdata idx 0)
(setval (keypath idx) 0 data) (setval (keypath idx) 0 data)
@ -245,26 +252,26 @@
[k (rand)])) [k (rand)]))
tdata (transient data)] tdata (transient data)]
(run-benchmark "transient comparison: submap" (run-benchmark "transient comparison: submap"
300000 150000
(transform (submap [600 700]) modify-submap data) (transform (submap [600 700]) modify-submap data)
(transform (submap! [600 700]) modify-submap tdata))) (transform (submap! [600 700]) modify-submap tdata)))
(let [data {:x 1} (let [data {:x 1}
meta-map {:my :metadata}] meta-map {:my :metadata}]
(run-benchmark "set metadata" (run-benchmark "set metadata"
2000000 1500000
(with-meta data meta-map) (with-meta data meta-map)
(setval META meta-map data))) (setval META meta-map data)))
(let [data (with-meta {:x 1} {:my :metadata})] (let [data (with-meta {:x 1} {:my :metadata})]
(run-benchmark "get metadata" (run-benchmark "get metadata"
20000000 15000000
(meta data) (meta data)
(select-any META data))) (select-any META data)))
(let [data (with-meta {:x 1} {:my :metadata})] (let [data (with-meta {:x 1} {:my :metadata})]
(run-benchmark "vary metadata" (run-benchmark "vary metadata"
2000000 800000
(vary-meta data assoc :y 2) (vary-meta data assoc :y 2)
(setval [META :y] 2 data))) (setval [META :y] 2 data)))