In one my the TMD pathways (that came from mastodon) we expand the dataset size using defrecords. Surprisingly considering everything else that performance case is doing, implementing IReduceInit spend up the timings considerably.
tech.v3.dataset.reductions-test> (require '[criterium.core :as crit])
nil
tech.v3.dataset.reductions-test> (defrecord YMC [year-month ^long count]
;; clojure.lang.IReduceInit
;; (reduce [this rfn init]
;; (let [init (reduced-> rfn init
;; (clojure.lang.MapEntry/create :year-month year-month)
;; (clojure.lang.MapEntry/create :count count))]
;; (if (and __extmap (not (reduced? init)))
;; (reduce rfn init __extmap)
;; init)))
)
tech.v3.dataset.reductions_test.YMC
tech.v3.dataset.reductions-test> (let [yc (YMC. :a 1)]
(crit/quick-bench (reduce (fn [acc v] v) nil yc)))
Evaluation count : 6729522 in 6 samples of 1121587 calls.
Execution time mean : 87.375170 ns
Execution time std-deviation : 0.173728 ns
Execution time lower quantile : 87.104982 ns ( 2.5%)
Execution time upper quantile : 87.550708 ns (97.5%)
Overhead used : 2.017589 ns
nil
tech.v3.dataset.reductions-test> (defrecord YMC [year-month ^long count]
clojure.lang.IReduceInit
(reduce [this rfn init]
(let [init (reduced-> rfn init
(clojure.lang.MapEntry/create :year-month year-month)
(clojure.lang.MapEntry/create :count count))]
(if (and __extmap (not (reduced? init)))
(reduce rfn init __extmap)
init)))
)
tech.v3.dataset.reductions_test.YMC
tech.v3.dataset.reductions-test> (let [yc (YMC. :a 1)]
(crit/quick-bench (reduce (fn [acc v] v) nil yc)))
Evaluation count : 43415358 in 6 samples of 7235893 calls.
Execution time mean : 11.775423 ns
Execution time std-deviation : 0.197683 ns
Execution time lower quantile : 11.594695 ns ( 2.5%)
Execution time upper quantile : 12.079668 ns (97.5%)
Overhead used : 2.017589 ns
nil
tech.v3.dataset.reductions-test> (defmacro reduced->
[rfn acc & data]
(reduce (fn [expr next-val]
`(let [val# ~expr]
(if (reduced? val#)
val#
(~rfn val# ~next-val))))
acc
data))
#'tech.v3.dataset.reductions-test/reduced->
tech.v3.dataset.reductions-test>
Talking this over with other members it appears the value lookup pathway could also be optimized in the case when __extmap is not nil (it uses clojure.core/get as opposed to a direct getorDefault call.