Last active
July 13, 2024 16:58
-
-
Save lnostdal/1fbd9b3d2ddc7bff1830638ea88348cc to your computer and use it in GitHub Desktop.
Clojure: Performance of with-local-vars vs. atom vs. volatile vs. unsynchronized-mutable field
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Performance of with-local-vars vs. atom vs. volatile vs. unsynchronized-mutable field. | |
(definterface IOObject | |
(setVal [new-val]) | |
(getVal []) | |
(oswap [f]) | |
(oswap [f x]) | |
(oswap [f x y]) | |
(oswap [f x y z])) | |
(deftype OObject | |
[^:unsynchronized-mutable val] | |
IOObject | |
(setVal [o new-val] (set! val new-val)) | |
(getVal [o] val) | |
(oswap [o f] (set! val (f val))) | |
(oswap [o f x] (set! val (f val x))) | |
(oswap [o f x y] (set! val (f val x y))) | |
(oswap [o f x y z] (set! val (f val x y z))) | |
clojure.lang.IDeref | |
(deref [o] val)) | |
(defn blah [] | |
(with-local-vars [wlv 0] | |
(time | |
(dotimes [i 100000000] | |
(var-set wlv (inc ^long (var-get wlv))))) | |
(println @wlv))) | |
;; "Elapsed time: 9574.548806 msecs" | |
(defn blah [] | |
(let [a (atom 0)] | |
(time | |
(dotimes [i 100000000] | |
(swap! a (fn [^long val] (inc val))))) | |
(println @a))) | |
;; "Elapsed time: 1908.351393 msecs" | |
(defn blah [] | |
(let [v (volatile! 0)] | |
(time | |
(dotimes [i 100000000] | |
(vswap! v (fn [^long val] (inc val))))) | |
(println @v))) | |
;; "Elapsed time: 1000.284472 msecs" | |
(defn blah [] | |
(let [o (OObject. 0)] | |
(time | |
(dotimes [i 100000000] | |
(.oswap o (fn [^long val] (inc val))))) | |
(println @o))) | |
;; "Elapsed time: 437.329174 msecs" | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;; You can combine this into "bash in-place" (sort of) Clojure transients: | |
(defn blah1 [] | |
(let [x (OObject. {})] | |
(dotimes [i 50000000] | |
(.setVal x (assoc (.getVal x) :a (* i i)))) | |
(.getVal x))) | |
(defn blah2 [] | |
(let [x (OObject. (transient {}))] | |
(dotimes [i 50000000] | |
(.setVal x (assoc! (.getVal x) :a (* i i)))) | |
(persistent! (.getVal x)))) | |
quantataraxia.core> (loop [] | |
(println "blah1:") | |
(time (blah1)) | |
(newline) | |
(println "blah2:") | |
(time (blah2)) | |
(newline) | |
(recur)) | |
blah1: | |
"Elapsed time: 1267.678723 msecs" | |
blah2: | |
"Elapsed time: 533.646835 msecs" | |
blah1: | |
"Elapsed time: 1270.494604 msecs" | |
blah2: | |
"Elapsed time: 524.925682 msecs" | |
blah1: | |
"Elapsed time: 1199.423884 msecs" | |
blah2: | |
"Elapsed time: 488.822583 msecs" | |
blah1: | |
"Elapsed time: 1186.578578 msecs" | |
blah2: | |
"Elapsed time: 536.999552 msecs" | |
;; ~60% improvement |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment