diff --git a/src/methodical/impl/cache/simple.clj b/src/methodical/impl/cache/simple.clj index f4bad81..5c7588d 100644 --- a/src/methodical/impl/cache/simple.clj +++ b/src/methodical/impl/cache/simple.clj @@ -8,6 +8,7 @@ [methodical.util.describe :as describe] [pretty.core :as pretty]) (:import + (clojure.lang IPersistentMap IDeref) (methodical.interface Cache))) (set! *warn-on-reflection* true) @@ -21,7 +22,8 @@ Cache (cached-method [_ dispatch-value] - (get @atomm dispatch-value)) + ;; This code is very hot, hence direct interop makes a difference here. + (.valAt ^IPersistentMap (.deref ^IDeref atomm) dispatch-value)) (cache-method! [_ dispatch-value method] (swap! atomm assoc dispatch-value method)) diff --git a/src/methodical/impl/multifn/cached.clj b/src/methodical/impl/multifn/cached.clj index f473eda..3cbfeb1 100644 --- a/src/methodical/impl/multifn/cached.clj +++ b/src/methodical/impl/multifn/cached.clj @@ -54,26 +54,26 @@ (CachedMultiFnImpl. new-impl (i/empty-copy cache))))) (effective-method [_ dispatch-value] - (or - (.cached-method cache dispatch-value) - ;; just like vanilla multimethods, we will add a new entry for every unique dispatch value we encounter, so - ;; there's an implicit assumption that dispatch values are bounded - ;; - ;; build the effective method for dispatch value. We may end up throwing this out, but we currently need to build - ;; it to determine the effective dispatch value. - (let [method (i/effective-method impl dispatch-value) - effective-dispatch-value (:dispatch-value (meta method)) - ;; If a method with the same effective dispatch value is already cached, add the existing method to the - ;; cache for dispatch value. This way we don't end up with a bunch of duplicate methods impls for various - ;; dispatch values that have the same effective dispatch value - cached-effective-dv-method (.cached-method cache effective-dispatch-value) - method (or cached-effective-dv-method method)] - ;; Make sure the method was cached for the effective dispatch value as well, that way if some less-specific - ;; dispatch value comes along with the same effective dispatch value we can use the existing method - (when-not cached-effective-dv-method - (i/cache-method! cache effective-dispatch-value method)) - (i/cache-method! cache dispatch-value method) - method))) + (if-some [cached (.cached-method cache dispatch-value)] + cached + ;; just like vanilla multimethods, we will add a new entry for every unique dispatch value we encounter, so + ;; there's an implicit assumption that dispatch values are bounded + ;; + ;; build the effective method for dispatch value. We may end up throwing this out, but we currently need to build + ;; it to determine the effective dispatch value. + (let [method (i/effective-method impl dispatch-value) + effective-dispatch-value (:dispatch-value (meta method)) + ;; If a method with the same effective dispatch value is already cached, add the existing method to the + ;; cache for dispatch value. This way we don't end up with a bunch of duplicate methods impls for various + ;; dispatch values that have the same effective dispatch value + cached-effective-dv-method (.cached-method cache effective-dispatch-value) + method (or cached-effective-dv-method method)] + ;; Make sure the method was cached for the effective dispatch value as well, that way if some less-specific + ;; dispatch value comes along with the same effective dispatch value we can use the existing method + (when-not cached-effective-dv-method + (i/cache-method! cache effective-dispatch-value method)) + (i/cache-method! cache dispatch-value method) + method))) clojure.protocols/Datafiable (datafy [this]