Details
-
Type:
Enhancement
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: Release 1.6
-
Fix Version/s: Release 1.6
-
Component/s: None
-
Labels:None
-
Patch:Code
Description
The attached patch changes zipmap to use a transient map internally. The definition is also moved so that it resides below that of #'transient. The original definition is commented out (like that of #'into).
Hi Aaron,
Thanks for looking into this!
From what I've been able to observe, this change hugely improves zipmap times for large maps. For small maps, there is a small improvement. Here are two basic Criterium benchmarks (transient-zipmap defined at the REPL as in the patch):
;;; large map user=> (def xs (range 16384)) #'user/xs user=> (last xs) 16383 user=> (c/bench (zipmap xs xs)) Evaluation count : 13920 in 60 samples of 232 calls. Execution time mean : 4.329635 ms Execution time std-deviation : 77.791989 us Execution time lower quantile : 4.215050 ms ( 2.5%) Execution time upper quantile : 4.494120 ms (97.5%) nil user=> (c/bench (transient-zipmap xs xs)) Evaluation count : 21180 in 60 samples of 353 calls. Execution time mean : 2.818339 ms Execution time std-deviation : 110.751493 us Execution time lower quantile : 2.618971 ms ( 2.5%) Execution time upper quantile : 3.025812 ms (97.5%) Found 2 outliers in 60 samples (3.3333 %) low-severe 2 (3.3333 %) Variance from outliers : 25.4675 % Variance is moderately inflated by outliers nil ;;; small map user=> (def ys (range 16)) #'user/ys user=> (last ys) 15 user=> (c/bench (zipmap ys ys)) Evaluation count : 16639020 in 60 samples of 277317 calls. Execution time mean : 3.803683 us Execution time std-deviation : 88.431220 ns Execution time lower quantile : 3.638146 us ( 2.5%) Execution time upper quantile : 3.935160 us (97.5%) nil user=> (c/bench (transient-zipmap ys ys)) Evaluation count : 18536880 in 60 samples of 308948 calls. Execution time mean : 3.412992 us Execution time std-deviation : 81.338284 ns Execution time lower quantile : 3.303888 us ( 2.5%) Execution time upper quantile : 3.545549 us (97.5%) nilClearly the semantics are preserved provided transients satisfy their contract.
I think I might not have started a ggroup thread for this, sorry.
;;; large map user=> (def xs (range 16384)) #'user/xs user=> (last xs) 16383 user=> (c/bench (zipmap xs xs)) Evaluation count : 13920 in 60 samples of 232 calls. Execution time mean : 4.329635 ms Execution time std-deviation : 77.791989 us Execution time lower quantile : 4.215050 ms ( 2.5%) Execution time upper quantile : 4.494120 ms (97.5%) nil user=> (c/bench (transient-zipmap xs xs)) Evaluation count : 21180 in 60 samples of 353 calls. Execution time mean : 2.818339 ms Execution time std-deviation : 110.751493 us Execution time lower quantile : 2.618971 ms ( 2.5%) Execution time upper quantile : 3.025812 ms (97.5%) Found 2 outliers in 60 samples (3.3333 %) low-severe 2 (3.3333 %) Variance from outliers : 25.4675 % Variance is moderately inflated by outliers nil ;;; small map user=> (def ys (range 16)) #'user/ys user=> (last ys) 15 user=> (c/bench (zipmap ys ys)) Evaluation count : 16639020 in 60 samples of 277317 calls. Execution time mean : 3.803683 us Execution time std-deviation : 88.431220 ns Execution time lower quantile : 3.638146 us ( 2.5%) Execution time upper quantile : 3.935160 us (97.5%) nil user=> (c/bench (transient-zipmap ys ys)) Evaluation count : 18536880 in 60 samples of 308948 calls. Execution time mean : 3.412992 us Execution time std-deviation : 81.338284 ns Execution time lower quantile : 3.303888 us ( 2.5%) Execution time upper quantile : 3.545549 us (97.5%) nil