mirror of
https://github.com/metosin/reitit.git
synced 2025-12-16 16:01:11 +00:00
Faster path conflict resolution, O(n2) -> O(n)
This commit is contained in:
parent
b128a0f3db
commit
1b0cc0a100
3 changed files with 22 additions and 18 deletions
|
|
@ -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 {}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue