sci
sci copied to clipboard
Optimize protocol/multi-method calls
Example:
$ cat /tmp/foo.clj
(defrecord Example []
clojure.lang.IDeref
(deref [this] :deref)
clojure.lang.IAtom
(reset [this new-value] :reset)
(swap [this f] :swap)
(swap [this f a] :swap)
(swap [this f a b] :swap)
(swap [this f a b args] :swap)
(compareAndSet [this oldv newv] true))
(time
[@(->Example)
(reset! (->Example) 1)
(swap! (->Example) inc)
(swap! (->Example) + 1)
(swap! (->Example) + 1 2)
(swap! (->Example) + 1 2 3)
(compare-and-set! (->Example) 1 2)])
This is much slower in bb than on the JVM:
$ ~/Downloads/bb-ideref /tmp/foo.clj
"Elapsed time: 0.15758 msecs"
[:deref :reset :swap :swap :swap :swap true]
$ clj /tmp/foo.clj
"Elapsed time: 0.063916 msecs"
Apply is much slower than a regular fn-call, this might be one of the causes.
user=> (time (dotimes [i 1000000000] (foo 1 2)))
"Elapsed time: 2534.94129 msecs"
nil
user=> (time (dotimes [i 1000000000] (apply foo [1 2])))
"Elapsed time: 37887.344147 msecs"
nil