Skip to content

Commit e4f2ac6

Browse files
committed
CLJS-2656: module-graph/validate-inputs takes forever for complex projects
fix validate-inputs performance, memoize doesn't help because the path & seen arguments are changing even for nses we've seen before. Instead track the state of validated nses and skip ones we've seen before. Because validate-inputs gets inputs in dep order, this is pretty fast now.
1 parent 424af2a commit e4f2ac6

1 file changed

Lines changed: 18 additions & 10 deletions

File tree

src/main/clojure/cljs/module_graph.cljc

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@
9393
(assoc ret module-name module')))
9494
{} modules))
9595

96+
(defn normalize-input [input]
97+
(-> input
98+
(update :provides #(into [] (map (comp str comp/munge)) %))
99+
(update :requires #(into [] (map (comp str comp/munge)) %))))
100+
96101
(defn index-inputs
97102
"Index compiler inputs by :provides. If an input has multiple entries
98103
in :provides will result in multiple entries in the map. The keys will be munged
@@ -105,14 +110,12 @@
105110
(fn [provide]
106111
(vector
107112
(-> provide comp/munge str)
108-
(-> input
109-
(update :provides #(into [] (map (comp str comp/munge)) %))
110-
(update :requires #(into [] (map (comp str comp/munge)) %))))))
113+
(-> input normalize-input))))
111114
provides))
112115
{} inputs))
113116

114-
(defn ^:dynamic validate-inputs*
115-
[indexed path seen]
117+
(defn validate-inputs*
118+
[indexed path seen validated]
116119
(let [ns (peek path)
117120
{:keys [requires]} (get indexed ns)]
118121
(doseq [ns' requires]
@@ -122,17 +125,22 @@
122125
(str "Circular dependency detected "
123126
(apply str (interpose " -> " (conj path ns'))))
124127
{:cljs.closure/error :invalid-inputs}))
125-
(validate-inputs* indexed (conj path ns') (conj seen ns'))))))
128+
(when-not (contains? @validated ns)
129+
(validate-inputs* indexed (conj path ns') (conj seen ns') validated))))
130+
(swap! validated conj ns)))
126131

127132
(defn validate-inputs
128133
"Throws on the presence of circular dependencies"
129134
([inputs]
130135
(validate-inputs inputs [] #{}))
131136
([inputs path seen]
132-
(let [indexed (index-inputs inputs)]
133-
(binding [validate-inputs* (memoize validate-inputs*)]
134-
(doseq [[ns] (seq indexed)]
135-
(validate-inputs* indexed (conj path ns) (conj seen ns)))))))
137+
(let [indexed (index-inputs inputs)
138+
validated (atom #{})]
139+
(binding []
140+
(doseq [{:keys [provides]} (map normalize-input inputs)]
141+
(let [ns (first provides)]
142+
(validate-inputs* indexed (conj path ns) (conj seen ns) validated)
143+
(swap! validated conj ns)))))))
136144

137145
(defn ^:dynamic deps-for
138146
"Return all dependencies for x in a graph using deps-key."

0 commit comments

Comments
 (0)