From 853f25da8c3c9ec3641b13175e25d74b31119e59 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Fri, 27 Oct 2023 14:46:12 +0200 Subject: [PATCH] Optimize deref, swap!, reset! for host values --- src/sci/impl/core_protocols.cljc | 46 ++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/sci/impl/core_protocols.cljc b/src/sci/impl/core_protocols.cljc index 286e814a..2bcb61ac 100644 --- a/src/sci/impl/core_protocols.cljc +++ b/src/sci/impl/core_protocols.cljc @@ -20,8 +20,13 @@ (defn deref* ([x] - #?(:clj (deref x) - :cljs (-deref x))) + #?(:clj (if (instance? clojure.lang.IDeref x) + (clojure.core/deref x) + (deref x)) + :cljs (if (or (instance? Atom x) + (implements? IDeref x)) + (clojure.core/deref x) + (-deref x)))) #?(:clj ([x & args] (apply clojure.core/deref x args)))) @@ -139,26 +144,45 @@ ;;;; Re-routing (defn swap!* [ref f & args] - ;; TODO: optimize arities - maybe test first how much this matters at all - ;; For CLJ I guess we can directly use the multimethods - (if args - (apply #?(:clj swap :cljs -swap!) ref f args) - (#?(:clj swap :cljs -swap!) ref f))) + (if + ;; fast-path for host IAtom + #?(:cljs (or (instance? Atom ref) + (implements? ISwap ref)) + :clj (instance? clojure.lang.IAtom ref)) + (if args + (apply clojure.core/swap! ref f args) + (clojure.core/swap! ref f)) + (if args + (apply #?(:clj swap :cljs -swap!) ref f args) + (#?(:clj swap :cljs -swap!) ref f)))) (defn reset!* [ref v] - (#?(:clj reset :cljs -reset!) ref v)) + (if + ;; fast-path for host IAtoms + #?(:cljs (or (instance? Atom ref) + (implements? IReset ref)) + :clj (instance? clojure.lang.IAtom ref)) + (clojure.core/reset! ref v) + (#?(:clj reset :cljs -reset!) ref v))) #?(:clj (defn compare-and-set!* [ref old new] - (compareAndSet ref old new))) + (if (instance? clojure.lang.IAtom ref) + ;; fast-path for host IAtoms + (clojure.core/compare-and-set! ref old new) + (compareAndSet ref old new)))) #?(:clj (defn swap-vals!* [ref f & args] - (apply swapVals ref f args))) + (if (instance? clojure.lang.IAtom ref) + (apply clojure.core/swap-vals! ref f args) + (apply swapVals ref f args)))) #?(:clj (defn reset-vals!* [ref v] - (resetVals ref v))) + (if (instance? clojure.lang.IAtom ref) + (clojure.core/reset-vals! ref v) + (resetVals ref v)))) ;;;; Protocol vars