10x perf improvement on safe-merge

safe merge was using way too much inefficient code for such an important
function
it is rewritten using a reduce. the performance improvement is 10 times
and should really show up when adding messages
in repl session the new merge was much slower on the error case of merging
fx with common keys but it must never happen in production as it means
the app is broken

status-im.utils.fx> (time (dotimes [x 100] (fast-merge {:a 1 :b 2 :filters/load-filters [{:a 1 :b 2}]} {:c 3 :filters/load-filters [{:d 1 :b x}]})))
"Elapsed time: 19.000000 msecs"
nil
status-im.utils.fx> (time (dotimes [x 100] (safe-merge {:a 1 :b 2 :filters/load-filters [{:a 1 :b 2}]} {:c 3 :filters/load-filters [{:d 1 :b x}]})))
"Elapsed time: 183.000000 msecs"

status-im.utils.fx> (time (dotimes [x 100] (fast-merge {:a 1 :c 2 :filters/load-filters [{:a 1 :b 2}]} {:c 3 :filters/load-filters [{:d 1 :b x}]})))
"Elapsed time: 2224.000000 msecs"
This commit is contained in:
yenda 2019-09-15 13:57:13 +02:00
parent 747dec908e
commit ee042bd1c4
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
1 changed files with 20 additions and 19 deletions

View File

@ -4,14 +4,14 @@
[status-im.ethereum.json-rpc :as json-rpc]
[taoensso.timbre :as log]
status-im.utils.handlers)
(:refer-clojure :exclude [merge]))
(:refer-clojure :exclude [merge reduce]))
(defn- update-db [cofx fx]
(if-let [db (:db fx)]
(assoc cofx :db db)
cofx))
(def ^:private mergable-keys
(def ^:private mergeable-keys
#{:chat-received-message/add-fx
:filters/load-filters
:pairing/set-installation-metadata
@ -27,16 +27,17 @@
(defn- safe-merge [fx new-fx]
(if (:merging-fx-with-common-keys fx)
fx
(let [common-keys (set/intersection (into #{} (keys fx))
(into #{} (keys new-fx)))]
(if (empty? (set/difference common-keys (conj mergable-keys :db)))
(clojure.core/merge (apply dissoc fx mergable-keys)
(apply dissoc new-fx mergable-keys)
(merge-with into
(select-keys fx mergable-keys)
(select-keys new-fx mergable-keys)))
(do (log/error "Merging fx with common-keys: " common-keys)
{:merging-fx-with-common-keys common-keys})))))
(clojure.core/reduce (fn [merged-fx [k v]]
(if (= :db k)
(assoc merged-fx :db v)
(if (get merged-fx k)
(if (mergeable-keys k)
(update merged-fx k into v)
(do (log/error "Merging fx with common-key: " k v)
(reduced {:merging-fx-with-common-keys k})))
(assoc merged-fx k v))))
fx
new-fx)))
(defn merge
"Takes a map of co-effects and forms as argument.
@ -51,10 +52,10 @@
(let [[first-arg & rest-args] args
initial-fxs? (map? first-arg)
fx-fns (if initial-fxs? rest-args args)]
(reduce (fn [fxs fx-fn]
(let [updated-cofx (update-db cofx fxs)]
(if fx-fn
(safe-merge fxs (fx-fn updated-cofx))
fxs)))
(if initial-fxs? first-arg {:db db})
fx-fns)))
(clojure.core/reduce (fn [fxs fx-fn]
(let [updated-cofx (update-db cofx fxs)]
(if fx-fn
(safe-merge fxs (fx-fn updated-cofx))
fxs)))
(if initial-fxs? first-arg {:db db})
fx-fns)))