Faster path conflict resolution, O(n2) -> O(n)

This commit is contained in:
Tommi Reiman 2020-04-27 08:38:27 +03:00
parent b128a0f3db
commit 1b0cc0a100
3 changed files with 22 additions and 18 deletions

View file

@ -74,14 +74,15 @@
coerce (into [] (keep #(coerce % opts))))) coerce (into [] (keep #(coerce % opts)))))
(defn path-conflicting-routes [routes opts] (defn path-conflicting-routes [routes opts]
(-> (into {} (let [parts-and-routes (mapv (fn [[s :as r]] [(trie/split-path s opts) r]) routes)]
(comp (map-indexed (fn [index route] (-> (into {} (comp (map-indexed (fn [index [p r]]
[route (into #{} [r (reduce
(filter #(trie/conflicting-paths? (first route) (first %) opts)) (fn [acc [p' r']]
(subvec routes (inc index)))])) (if (trie/conflicting-parts? p p')
(filter (comp seq second))) (conj acc r') acc))
routes) #{} (subvec parts-and-routes (inc index)))]))
(not-empty))) (filter (comp seq second))) parts-and-routes)
(not-empty))))
(defn unresolved-conflicts [path-conflicting] (defn unresolved-conflicts [path-conflicting]
(-> (into {} (-> (into {}

View file

@ -132,17 +132,18 @@
(concat [(subs x i)] xs) (concat [(subs x i)] xs)
xs))) xs)))
(defn conflicting-parts? [parts1 parts2]
(let [[[s1 & ss1] [s2 & ss2]] (-slice-start parts1 parts2)]
(cond
(= s1 s2 nil) true
(or (nil? s1) (nil? s2)) false
(or (catch-all? s1) (catch-all? s2)) true
(or (wild? s1) (wild? s2)) (recur (-slice-end s1 ss1) (-slice-end s2 ss2))
(not= s1 s2) false
:else (recur ss1 ss2))))
(defn conflicting-paths? [path1 path2 opts] (defn conflicting-paths? [path1 path2 opts]
(loop [parts1 (split-path path1 opts) (conflicting-parts? (split-path path1 opts) (split-path path2 opts)))
parts2 (split-path path2 opts)]
(let [[[s1 & ss1] [s2 & ss2]] (-slice-start parts1 parts2)]
(cond
(= s1 s2 nil) true
(or (nil? s1) (nil? s2)) false
(or (catch-all? s1) (catch-all? s2)) true
(or (wild? s1) (wild? s2)) (recur (-slice-end s1 ss1) (-slice-end s2 ss2))
(not= s1 s2) false
:else (recur ss1 ss2)))))
;; ;;
;; Creating Tries ;; Creating Tries

View file

@ -40,6 +40,7 @@
(suite "non-conflicting") (suite "non-conflicting")
;; 104ms ;; 104ms
;; 11ms (reuse parts in conflict resolution)
(bench! "default" (r/router hundred-routes)) (bench! "default" (r/router hundred-routes))
;; 7ms ;; 7ms
@ -50,6 +51,7 @@
;; 205ms ;; 205ms
;; 105ms (cache path-conflicts) ;; 105ms (cache path-conflicts)
;; 13ms (reuse parts in conflict resolution)
(bench! "default" (r/router routes {:conflicts nil})))) (bench! "default" (r/router routes {:conflicts nil}))))
(comment (comment