huge speedup to cljs version by optimizing field access

This commit is contained in:
Nathan Marz 2015-07-01 10:30:51 -04:00
parent 71b3f6e462
commit 859b31bce7
3 changed files with 49 additions and 46 deletions

View file

@ -0,0 +1,4 @@
(ns com.rpl.specter.field-clj)
(defmacro field [obj field]
`(. ~obj ~field))

View file

@ -0,0 +1,6 @@
(ns com.rpl.specter.field-cljs)
(defmacro field [obj field]
(let [getter (symbol (str ".-" field))]
`(~getter ~obj)
))

View file

@ -1,23 +1,16 @@
(ns com.rpl.specter.impl (ns com.rpl.specter.impl
#?(:cljs (:require-macros
[com.rpl.specter.field-cljs :refer [field]]))
(:use [com.rpl.specter.protocols :only (:use [com.rpl.specter.protocols :only
[comp-paths* [comp-paths*
select* transform* collect-val select-full* transform-full*]]) select* transform* collect-val select-full* transform-full*]]
#?(:clj [com.rpl.specter.field-clj :only [field]]))
(:require [com.rpl.specter.protocols :as p] (:require [com.rpl.specter.protocols :as p]
[clojure.walk :as walk] [clojure.walk :as walk]
[clojure.core.reducers :as r] [clojure.core.reducers :as r]
[clojure.string :as s]) [clojure.string :as s])
) )
#?(
:clj
(defmacro field [obj quoted-field]
`(. ~obj ~(second quoted-field)))
:cljs
(defn field [obj field]
(aget obj (s/replace (str field) "-" "_")))
)
#?( #?(
:clj :clj
(do (do
@ -231,16 +224,16 @@
(defn extype [^TransformFunctions f] (defn extype [^TransformFunctions f]
(let [^ExecutorFunctions exs (field f 'executors)] (let [^ExecutorFunctions exs (field f executors)]
(field exs 'type) (field exs type)
)) ))
(defn- combine-same-types [[^TransformFunctions f & _ :as all]] (defn- combine-same-types [[^TransformFunctions f & _ :as all]]
(if (empty? all) (if (empty? all)
(coerce-path nil) (coerce-path nil)
(let [^ExecutorFunctions exs (field f 'executors) (let [^ExecutorFunctions exs (field f executors)
t (field exs 'type) t (field exs type)
combiner combiner
(if (= t :svalspath) (if (= t :svalspath)
@ -258,16 +251,16 @@
(reduce (fn [^TransformFunctions curr ^TransformFunctions next] (reduce (fn [^TransformFunctions curr ^TransformFunctions next]
(->TransformFunctions (->TransformFunctions
exs exs
(combiner (field curr 'selector) (field next 'selector)) (combiner (field curr selector) (field next selector))
(combiner (field curr 'transformer) (field next 'transformer)) (combiner (field curr transformer) (field next transformer))
)) ))
all)))) all))))
(defn coerce-structure-vals [^TransformFunctions tfns] (defn coerce-structure-vals [^TransformFunctions tfns]
(if (= (extype tfns) :svalspath) (if (= (extype tfns) :svalspath)
tfns tfns
(let [selector (field tfns 'selector) (let [selector (field tfns selector)
transformer (field tfns 'transformer)] transformer (field tfns transformer)]
(->TransformFunctions (->TransformFunctions
StructureValsPathExecutor StructureValsPathExecutor
(fn [vals structure next-fn] (fn [vals structure next-fn]
@ -333,7 +326,7 @@
(set_cell cell val)) (set_cell cell val))
(defn get-cell [cell] (defn get-cell [cell]
#?(:clj (get_cell cell) :cljs (field cell 'q)) #?(:clj (get_cell cell) :cljs (field cell q))
) )
(defn update-cell! [cell afn] (defn update-cell! [cell afn]
@ -392,14 +385,14 @@
(defn compiled-select* (defn compiled-select*
[^com.rpl.specter.impl.TransformFunctions tfns structure] [^com.rpl.specter.impl.TransformFunctions tfns structure]
(let [^com.rpl.specter.impl.ExecutorFunctions ex (field tfns 'executors)] (let [^com.rpl.specter.impl.ExecutorFunctions ex (field tfns executors)]
((field ex 'select-executor) (field tfns 'selector) structure) ((field ex select-executor) (field tfns selector) structure)
)) ))
(defn compiled-transform* (defn compiled-transform*
[^com.rpl.specter.impl.TransformFunctions tfns transform-fn structure] [^com.rpl.specter.impl.TransformFunctions tfns transform-fn structure]
(let [^com.rpl.specter.impl.ExecutorFunctions ex (field tfns 'executors)] (let [^com.rpl.specter.impl.ExecutorFunctions ex (field tfns executors)]
((field ex 'transform-executor) (field tfns 'transformer) transform-fn structure) ((field ex transform-executor) (field tfns transformer) transform-fn structure)
)) ))
(defn selected?* (defn selected?*
@ -468,29 +461,29 @@
PosStructurePath PosStructurePath
(select* [this structure next-fn] (select* [this structure next-fn]
(if-not (empty? structure) (if-not (empty? structure)
(next-fn ((field this 'getter) structure)))) (next-fn ((field this getter) structure))))
(transform* [this structure next-fn] (transform* [this structure next-fn]
(if (empty? structure) (if (empty? structure)
structure structure
((field this 'setter) structure (next-fn ((field this 'getter) structure)))))) ((field this setter) structure (next-fn ((field this getter) structure))))))
(deftype WalkerStructurePath [afn]) (deftype WalkerStructurePath [afn])
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
WalkerStructurePath WalkerStructurePath
(select* [^WalkerStructurePath this structure next-fn] (select* [^WalkerStructurePath this structure next-fn]
(walk-select (field this 'afn) next-fn structure)) (walk-select (field this afn) next-fn structure))
(transform* [^WalkerStructurePath this structure next-fn] (transform* [^WalkerStructurePath this structure next-fn]
(walk-until (field this 'afn) next-fn structure))) (walk-until (field this afn) next-fn structure)))
(deftype CodeWalkerStructurePath [afn]) (deftype CodeWalkerStructurePath [afn])
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
CodeWalkerStructurePath CodeWalkerStructurePath
(select* [^CodeWalkerStructurePath this structure next-fn] (select* [^CodeWalkerStructurePath this structure next-fn]
(walk-select (field this 'afn) next-fn structure)) (walk-select (field this afn) next-fn structure))
(transform* [^CodeWalkerStructurePath this structure next-fn] (transform* [^CodeWalkerStructurePath this structure next-fn]
(codewalk-until (field this 'afn) next-fn structure))) (codewalk-until (field this afn) next-fn structure)))
(deftype FilterStructurePath [path]) (deftype FilterStructurePath [path])
@ -498,9 +491,9 @@
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
FilterStructurePath FilterStructurePath
(select* [^FilterStructurePath this structure next-fn] (select* [^FilterStructurePath this structure next-fn]
(->> structure (filter #(selected?* (field this 'path) %)) doall next-fn)) (->> structure (filter #(selected?* (field this path) %)) doall next-fn))
(transform* [^FilterStructurePath this structure next-fn] (transform* [^FilterStructurePath this structure next-fn]
(let [[filtered ancestry] (filter+ancestry (field this 'path) structure) (let [[filtered ancestry] (filter+ancestry (field this path) structure)
;; the vec is necessary so that we can get by index later ;; the vec is necessary so that we can get by index later
;; (can't get by index for cons'd lists) ;; (can't get by index for cons'd lists)
next (vec (next-fn filtered))] next (vec (next-fn filtered))]
@ -514,9 +507,9 @@
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
KeyPath KeyPath
(select* [^KeyPath this structure next-fn] (select* [^KeyPath this structure next-fn]
(key-select (field this 'akey) structure next-fn)) (key-select (field this akey) structure next-fn))
(transform* [^KeyPath this structure next-fn] (transform* [^KeyPath this structure next-fn]
(key-transform (field this 'akey) structure next-fn) (key-transform (field this akey) structure next-fn)
)) ))
(deftype SelectCollector [sel-fn selector]) (deftype SelectCollector [sel-fn selector])
@ -524,20 +517,20 @@
(extend-protocol p/Collector (extend-protocol p/Collector
SelectCollector SelectCollector
(collect-val [^SelectCollector this structure] (collect-val [^SelectCollector this structure]
((field this 'sel-fn) (field this 'selector) structure))) ((field this sel-fn) (field this selector) structure)))
(deftype SRangePath [start-fn end-fn]) (deftype SRangePath [start-fn end-fn])
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
SRangePath SRangePath
(select* [^SRangePath this structure next-fn] (select* [^SRangePath this structure next-fn]
(let [start ((field this 'start-fn) structure) (let [start ((field this start-fn) structure)
end ((field this 'end-fn) structure)] end ((field this end-fn) structure)]
(next-fn (-> structure vec (subvec start end))) (next-fn (-> structure vec (subvec start end)))
)) ))
(transform* [^SRangePath this structure next-fn] (transform* [^SRangePath this structure next-fn]
(let [start ((field this 'start-fn) structure) (let [start ((field this start-fn) structure)
end ((field this 'end-fn) structure) end ((field this end-fn) structure)
structurev (vec structure) structurev (vec structure)
newpart (next-fn (-> structurev (subvec start end))) newpart (next-fn (-> structurev (subvec start end)))
res (concat (subvec structurev 0 start) res (concat (subvec structurev 0 start)
@ -553,9 +546,9 @@
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
ViewPath ViewPath
(select* [^ViewPath this structure next-fn] (select* [^ViewPath this structure next-fn]
(->> structure ((field this 'view-fn)) next-fn)) (->> structure ((field this view-fn)) next-fn))
(transform* [^ViewPath this structure next-fn] (transform* [^ViewPath this structure next-fn]
(->> structure ((field this 'view-fn)) next-fn) (->> structure ((field this view-fn)) next-fn)
)) ))
(deftype PutValCollector [val]) (deftype PutValCollector [val])
@ -563,7 +556,7 @@
(extend-protocol p/Collector (extend-protocol p/Collector
PutValCollector PutValCollector
(collect-val [^PutValCollector this structure] (collect-val [^PutValCollector this structure]
(field this 'val) (field this val)
)) ))
@ -592,12 +585,12 @@
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
ConditionalPath ConditionalPath
(select* [this structure next-fn] (select* [this structure next-fn]
(if-let [selector (retrieve-selector (field this 'cond-pairs) structure)] (if-let [selector (retrieve-selector (field this cond-pairs) structure)]
(->> (compiled-select* selector structure) (->> (compiled-select* selector structure)
(mapcat next-fn) (mapcat next-fn)
doall))) doall)))
(transform* [this structure next-fn] (transform* [this structure next-fn]
(if-let [selector (retrieve-selector (field this 'cond-pairs) structure)] (if-let [selector (retrieve-selector (field this cond-pairs) structure)]
(compiled-transform* selector next-fn structure) (compiled-transform* selector next-fn structure)
structure structure
))) )))
@ -607,7 +600,7 @@
(extend-protocol p/StructurePath (extend-protocol p/StructurePath
MultiPath MultiPath
(select* [this structure next-fn] (select* [this structure next-fn]
(->> (field this 'paths) (->> (field this paths)
(mapcat #(compiled-select* % structure)) (mapcat #(compiled-select* % structure))
(mapcat next-fn) (mapcat next-fn)
doall doall
@ -617,7 +610,7 @@
(fn [structure selector] (fn [structure selector]
(compiled-transform* selector next-fn structure)) (compiled-transform* selector next-fn structure))
structure structure
(field this 'paths)) (field this paths))
)) ))
(defn filter-select [afn structure next-fn] (defn filter-select [afn structure next-fn]