0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 02:28:18 -05:00

Revert some memoizes on page/helpers.

And improves base performance of get-children and
remove duplicated code. Also optimize the use
of get-children on react components with corresponding
use-memo hook.
This commit is contained in:
Andrey Antukh 2022-01-18 23:12:41 +01:00 committed by Andrés Moya
parent 1b3b3b0ee6
commit 072e4a4f98
5 changed files with 111 additions and 107 deletions

View file

@ -6,7 +6,9 @@
(ns app.common.geom.align
(:require
[app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :refer [get-children]]
[clojure.spec.alpha :as s]))
;; --- Alignment
@ -15,23 +17,13 @@
(declare calc-align-pos)
;; TODO: revisit on how to reuse code and dont have this function
;; duplicated because the implementation right now differs from the
;; original function.
;; Duplicated from pages/helpers to remove cyclic dependencies
(defn- get-children [id objects]
(let [shapes (vec (get-in objects [id :shapes]))]
(if shapes
(into shapes (mapcat #(get-children % objects)) shapes)
[])))
(defn- recursive-move
"Move the shape and all its recursive children."
[shape dpoint objects]
(let [children-ids (get-children (:id shape) objects)
children (map #(get objects %) children-ids)]
(map #(gsh/move % dpoint) (cons shape children))))
(->> (get-children (:id shape) objects)
(map (d/getf objects))
(cons shape)
(map #(gsh/move % dpoint))))
(defn align-to-rect
"Move the shape so that it is aligned with the given rectangle

View file

@ -412,7 +412,7 @@
{:rotation angle
:displacement displacement}))
(defn merge-modifiers*
(defn merge-modifiers
[objects modifiers]
(let [set-modifier
@ -422,8 +422,6 @@
(->> modifiers
(reduce set-modifier objects))))
(def merge-modifiers (memoize merge-modifiers*))
(defn modifiers->transform
([modifiers]
(modifiers->transform nil modifiers))

View file

@ -99,37 +99,10 @@
[component]
(get-in component [:objects (:id component)]))
;; Implemented with transient for performance
(defn get-children*
"Retrieve all children ids recursively for a given object. The
children's order will be breadth first."
[id objects]
(loop [result (transient [])
pending (transient [])
next id]
(let [children (get-in objects [next :shapes] [])
[result pending]
;; Iterate through children and add them to the result
;; also add them in pending to check for their children
(loop [result result
pending pending
current (first children)
children (rest children)]
(if current
(recur (conj! result current)
(conj! pending current)
(first children)
(rest children))
[result pending]))
;; If we have still pending, advance the iterator
length (count pending)]
(if (pos? length)
(let [next (get pending (dec length))]
(recur result (pop! pending) next))
(persistent! result)))))
(def get-children (memoize get-children*))
(defn get-children [id objects]
(if-let [shapes (-> (get objects id) :shapes (some-> vec))]
(into shapes (mapcat #(get-children % objects)) shapes)
[]))
(defn get-children-objects
"Retrieve all children objects recursively for a given object"
@ -175,7 +148,7 @@
shape
(get objects (:frame-id shape))))
(defn clean-loops*
(defn clean-loops
"Clean a list of ids from circular references."
[objects ids]
@ -192,8 +165,6 @@
(reduce add-element (d/ordered-set) ids)))
(def clean-loops (memoize clean-loops*))
(defn calculate-invalid-targets
[shape-id objects]
(let [result #{shape-id}

View file

@ -101,10 +101,12 @@
bool-shape (bool/bool-shape shape-wrapper)]
(mf/fnc bool-wrapper
[{:keys [shape] :as props}]
(let [childs (->> (cp/get-children (:id shape) objects)
(select-keys objects))]
[:& bool-shape {:shape shape
:childs childs}]))))
(let [childs (mf/use-memo
(mf/deps (:id shape) objects)
(fn []
(->> (cp/get-children (:id shape) objects)
(select-keys objects))))]
[:& bool-shape {:shape shape :childs childs}]))))
(defn svg-raw-wrapper-factory
[objects]
@ -221,26 +223,39 @@
(mf/defc frame-svg
{::mf/wrap [mf/memo]}
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
(let [modifier (-> (gpt/point (:x frame) (:y frame))
(gpt/negate)
(gmt/translate-matrix))
frame-id (:id frame)
(let [frame-id (:id frame)
include-metadata? (mf/use-ctx export/include-metadata-ctx)
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
objects (reduce update-fn objects modifier-ids)
frame (assoc-in frame [:modifiers :displacement] modifier)
modifier
(mf/use-memo
(mf/deps (:x frame) (:y frame))
(fn []
(-> (gpt/point (:x frame) (:y frame))
(gpt/negate)
(gmt/translate-matrix))))
objects
(mf/use-memo
(mf/deps frame-id objects modifier)
(fn []
(let [update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)]
(->> (cp/get-children frame-id objects)
(into [frame-id])
(reduce update-fn objects)))))
frame
(mf/use-memo
(mf/deps modifier)
(fn [] (assoc-in frame [:modifiers :displacement] modifier)))
wrapper
(mf/use-memo
(mf/deps objects)
(fn [] (frame-wrapper-factory objects)))
width (* (:width frame) zoom)
height (* (:height frame) zoom)
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})
wrapper (mf/use-memo
(mf/deps objects)
#(frame-wrapper-factory objects))]
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})]
[:svg {:view-box vbox
:width (ust/format-precision width viewbox-decimal-precision)
@ -254,19 +269,25 @@
(mf/defc component-svg
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
[{:keys [objects group zoom] :or {zoom 1} :as props}]
(let [modifier (-> (gpt/point (:x group) (:y group))
(gpt/negate)
(gmt/translate-matrix))
group-id (:id group)
(let [group-id (:id group)
include-metadata? (mf/use-ctx export/include-metadata-ctx)
modifier-ids (concat [group-id] (cp/get-children group-id objects))
modifier
(mf/use-memo
(mf/deps (:x group) (:y group))
(fn []
(-> (gpt/point (:x group) (:y group))
(gpt/negate)
(gmt/translate-matrix))))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
modifiers (reduce update-fn {} modifier-ids)
objects (gsh/merge-modifiers objects modifiers)
objects
(mf/use-memo
(mf/deps modifier objects group-id)
(fn []
(let [modifier-ids (concat [group-id] (cp/get-children group-id objects))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
modifiers (reduce update-fn {} modifier-ids)]
(gsh/merge-modifiers objects modifiers))))
group (get objects group-id)
width (* (:width group) zoom)
@ -276,7 +297,7 @@
group-wrapper
(mf/use-memo
(mf/deps objects)
#(group-wrapper-factory objects))]
(fn [] (group-wrapper-factory objects)))]
[:svg {:view-box vbox
:width (ust/format-precision width viewbox-decimal-precision)
@ -285,31 +306,51 @@
:xmlns "http://www.w3.org/2000/svg"
:xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")}
[:> shape-container {:shape group}
[:& group-wrapper {:shape group :view-box vbox}]]]))
(mf/defc component-symbol
[{:keys [id data] :as props}]
{::mf/wrap-props false}
[props]
(let [id (obj/get props "id")
data (obj/get props "data")
name (:name data)
path (:path data)
objects (:objects data)
root (get objects id)
selrect (:selrect root)
(let [{:keys [name path objects]} data
root (get objects id)
vbox
(format-viewbox
{:width (:width selrect)
:height (:height selrect)})
{:keys [width height]} (:selrect root)
vbox (format-viewbox {:width width :height height})
modifier
(mf/use-memo
(mf/deps (:x root) (:y root))
(fn []
(-> (gpt/point (:x root) (:y root))
(gpt/negate)
(gmt/translate-matrix))))
modifier (-> (gpt/point (:x root) (:y root))
(gpt/negate)
(gmt/translate-matrix))
objects
(mf/use-memo
(mf/deps modifier id objects)
(fn []
(let [modifier-ids (concat [id] (cp/get-children id objects))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)]
(reduce update-fn objects modifier-ids))))
modifier-ids (concat [id] (cp/get-children id objects))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
objects (reduce update-fn objects modifier-ids)
root (assoc-in root [:modifiers :displacement] modifier)
root
(mf/use-memo
(mf/deps modifier root)
(fn [] (assoc-in root [:modifiers :displacement] modifier)))
group-wrapper
(mf/use-memo
(mf/deps objects)
#(group-wrapper-factory objects))]
(fn [] (group-wrapper-factory objects)))]
[:> "symbol" #js {:id (str id)
:viewBox vbox
@ -321,10 +362,9 @@
(mf/defc components-sprite-svg
{::mf/wrap-props false}
[props]
(let [data (obj/get props "data")
children (obj/get props "children")
embed? (obj/get props "embed?")
(let [data (obj/get props "data")
children (obj/get props "children")
embed? (obj/get props "embed?")
include-metadata? (obj/get props "include-metadata?")]
[:& (mf/provider embed/context) {:value embed?}
[:& (mf/provider export/include-metadata-ctx) {:value include-metadata?}

View file

@ -96,18 +96,21 @@
::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
thumbnail? (unchecked-get props "thumbnail?")
(when-let [shape (unchecked-get props "shape")]
(let [objects (unchecked-get props "objects")
thumbnail? (unchecked-get props "thumbnail?")
children (-> (mapv (d/getf objects) (:shapes shape))
(hooks/use-equal-memo))
all-children (-> (cp/get-children-objects (:id shape) objects)
(hooks/use-equal-memo))
children
(-> (mapv (d/getf objects) (:shapes shape))
(hooks/use-equal-memo))
show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))]
all-children
(-> (cp/get-children-objects (:id shape) objects)
(hooks/use-equal-memo))
show-thumbnail?
(and thumbnail? (some? (:thumbnail shape)))]
(when (some? shape)
[:g.frame-wrapper {:display (when (:hidden shape) "none")}
[:> shape-container {:shape shape}
[:& ff/fontfaces-style {:shapes all-children}]