stop using ConcurrentHashMap for inline cache, instead intern a new var at macro-time. 17% performance improvement for [:a :b :c] benchmark

This commit is contained in:
Nathan Marz 2016-05-31 23:04:24 -04:00
parent a583540f21
commit fbca7ab99c
2 changed files with 7 additions and 24 deletions

View file

@ -724,23 +724,12 @@
params-maker ; can be null params-maker ; can be null
]) ])
#+clj
(defonce PATH-CACHE (java.util.concurrent.ConcurrentHashMap.))
(def MUST-CACHE-PATHS (mutable-cell false)) (def MUST-CACHE-PATHS (mutable-cell false))
(defn must-cache-paths! (defn must-cache-paths!
([] (must-cache-paths! true)) ([] (must-cache-paths! true))
([v] (set-cell! MUST-CACHE-PATHS v))) ([v] (set-cell! MUST-CACHE-PATHS v)))
#+clj
(defn add-path-cache! [k v]
(.put ^java.util.concurrent.ConcurrentHashMap PATH-CACHE k v))
#+clj
(defn get-path-cache [^String k]
(.get ^java.util.concurrent.ConcurrentHashMap PATH-CACHE k))
(defn- extract-original-code [p] (defn- extract-original-code [p]
(cond (cond
(instance? LocalSym p) (:sym p) (instance? LocalSym p) (:sym p)

View file

@ -435,29 +435,21 @@
prepared-path (ic-prepare-path local-syms expanded) prepared-path (ic-prepare-path local-syms expanded)
possible-params (vec (ic-possible-params expanded)) possible-params (vec (ic-possible-params expanded))
;; TODO: unclear if using long here versus string makes
;; a significant difference
;; - but using random longs creates possibility of collisions
;; (birthday problem)
;; - ideally could have a real inline cache that wouldn't
;; have to do any hashing/equality checking at all
;; - with invokedynamic here, could go directly to the code ;; - with invokedynamic here, could go directly to the code
;; to invoke and/or parameterize the precompiled path without ;; to invoke and/or parameterize the precompiled path without
;; a bunch of checks beforehand ;; a bunch of checks beforehand
cache-id (if (= platform :clj) (i/gen-uuid-str)) cache-sym (vary-meta
cache-sym (if (= platform :cljs) (gensym "pathcache")
(vary-meta assoc :cljs.analyzer/no-resolve true)
(gensym "pathcache")
assoc :cljs.analyzer/no-resolve true))
info-sym (gensym "info") info-sym (gensym "info")
get-cache-code (if (= platform :clj) get-cache-code (if (= platform :clj)
`(i/get-path-cache ~cache-id) `(i/get-cell ~cache-sym)
cache-sym cache-sym
) )
add-cache-code (if (= platform :clj) add-cache-code (if (= platform :clj)
`(i/add-path-cache! ~cache-id ~info-sym) `(i/set-cell! ~cache-sym ~info-sym)
`(def ~cache-sym ~info-sym)) `(def ~cache-sym ~info-sym))
@ -473,6 +465,8 @@
~(mapv (fn [p] `(fn [] ~p)) possible-params) ~(mapv (fn [p] `(fn [] ~p)) possible-params)
)) ))
] ]
(if (= platform :clj)
(intern *ns* cache-sym (i/mutable-cell)))
`(let [info# ~get-cache-code `(let [info# ~get-cache-code
^com.rpl.specter.impl.CachedPathInfo info# ^com.rpl.specter.impl.CachedPathInfo info#