mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 16:31:11 +00:00
Fast-router if only 1 static path.
* 200x faster on basic benchmark than the slowest one
This commit is contained in:
parent
254908b70b
commit
e9c0639914
3 changed files with 131 additions and 17 deletions
|
|
@ -66,9 +66,48 @@
|
|||
["/auth/recovery/token/:token" :auth/recovery]
|
||||
["/workspace/:project/:page" :workspace/page]]))
|
||||
|
||||
(defn routing-test []
|
||||
(defn routing-test1 []
|
||||
|
||||
(suite "simple routing")
|
||||
(suite "static route")
|
||||
|
||||
;; 2.2µs
|
||||
(title "bidi")
|
||||
(let [call #(bidi/match-route bidi-routes "/auth/login")]
|
||||
(assert (call))
|
||||
(cc/quick-bench
|
||||
(call)))
|
||||
|
||||
;; 1.5µs (-40%)
|
||||
(title "ataraxy")
|
||||
(let [call #(ataraxy/matches ataraxy-routes {:uri "/auth/login"})]
|
||||
(assert (call))
|
||||
(cc/quick-bench
|
||||
(call)))
|
||||
|
||||
;; 1.1µs (-50%)
|
||||
(title "pedestal - map-tree => prefix-tree")
|
||||
(let [call #(pedestal/find-route pedestal-router {:path-info "/auth/login" :request-method :get})]
|
||||
(assert (call))
|
||||
(cc/quick-bench
|
||||
(call)))
|
||||
|
||||
;; 1.5µs (-40%)
|
||||
(title "compojure-api")
|
||||
(let [call #(compojure-api-routes {:uri "/auth/login", :request-method :get})]
|
||||
(assert (call))
|
||||
(cc/quick-bench
|
||||
(call)))
|
||||
|
||||
;; 11.5ns (-99,5%)
|
||||
(title "reitit")
|
||||
(let [call #(reitit/match-by-path reitit-routes "/auth/login")]
|
||||
(assert (call))
|
||||
(cc/quick-bench
|
||||
(call))))
|
||||
|
||||
(defn routing-test2 []
|
||||
|
||||
(suite "wildcard route")
|
||||
|
||||
;; 15.4µs
|
||||
(title "bidi")
|
||||
|
|
@ -141,5 +180,6 @@
|
|||
(call))))
|
||||
|
||||
(comment
|
||||
(routing-test)
|
||||
(routing-test1)
|
||||
(routing-test2)
|
||||
(reverse-routing-test))
|
||||
|
|
|
|||
|
|
@ -213,17 +213,52 @@
|
|||
(if-let [match (impl/fast-get lookup name)]
|
||||
(match params)))))))
|
||||
|
||||
(defn fast-router
|
||||
"Creates a super-fast router of 1 static route(s) and optional
|
||||
expanded options. See [[router]] for available options"
|
||||
([routes]
|
||||
(fast-router routes {}))
|
||||
([routes opts]
|
||||
(when (or (not= (count routes) 1) (some impl/wild-route? routes))
|
||||
(throw
|
||||
(ex-info
|
||||
(str ":fast-router requires exactly 1 static route: " routes)
|
||||
{:routes routes})))
|
||||
(let [[n :as names] (find-names routes opts)
|
||||
[[p meta result] :as compiled] (compile-routes routes opts)
|
||||
p #?(:clj (.intern ^String p) :cljs p)
|
||||
match (->Match p meta result {} p)]
|
||||
(reify Router
|
||||
(router-name [_]
|
||||
:fast-router)
|
||||
(routes [_]
|
||||
compiled)
|
||||
(options [_]
|
||||
opts)
|
||||
(route-names [_]
|
||||
names)
|
||||
(match-by-path [_ path]
|
||||
(if (#?(:clj .equals :cljs =) p path)
|
||||
match))
|
||||
(match-by-name [_ name]
|
||||
(if (= n name)
|
||||
match))
|
||||
(match-by-name [_ name params]
|
||||
(if (= n name)
|
||||
(impl/fast-assoc match :params params)))))))
|
||||
|
||||
(defn mixed-router
|
||||
"Creates two routers: [[lookup-router]] for static routes and
|
||||
[[linear-router]] for wildcard routes. All routes should be
|
||||
non-conflicting. Takes resolved routes and optional
|
||||
"Creates two routers: [[lookup-router]] or [[fast-ruoter]] for
|
||||
static routes and [[linear-router]] for wildcard routes. All
|
||||
routes should be non-conflicting. Takes resolved routes and optional
|
||||
expanded options. See [[router]] for options."
|
||||
([routes]
|
||||
(mixed-router routes {}))
|
||||
([routes opts]
|
||||
(let [{linear true, lookup false} (group-by impl/wild-route? routes)
|
||||
linear-router (linear-router linear opts)
|
||||
lookup-router (lookup-router lookup opts)
|
||||
->static-router (if (= 1 (count lookup)) fast-router lookup-router)
|
||||
wildcard-router (linear-router linear opts)
|
||||
static-router (->static-router lookup opts)
|
||||
names (find-names routes opts)]
|
||||
(reify Router
|
||||
(router-name [_]
|
||||
|
|
@ -235,19 +270,19 @@
|
|||
(route-names [_]
|
||||
names)
|
||||
(match-by-path [_ path]
|
||||
(or (match-by-path lookup-router path)
|
||||
(match-by-path linear-router path)))
|
||||
(or (match-by-path static-router path)
|
||||
(match-by-path wildcard-router path)))
|
||||
(match-by-name [_ name]
|
||||
(or (match-by-name lookup-router name)
|
||||
(match-by-name linear-router name)))
|
||||
(or (match-by-name static-router name)
|
||||
(match-by-name wildcard-router name)))
|
||||
(match-by-name [_ name params]
|
||||
(or (match-by-name lookup-router name params)
|
||||
(match-by-name linear-router name params)))))))
|
||||
(or (match-by-name static-router name params)
|
||||
(match-by-name wildcard-router name params)))))))
|
||||
|
||||
(defn router
|
||||
"Create a [[Router]] from raw route data and optionally an options map.
|
||||
If routes contain wildcards, a [[LinearRouter]] is used, otherwise a
|
||||
[[LookupRouter]]. The following options are available:
|
||||
Selects implementation based on route details. The following options
|
||||
are available:
|
||||
|
||||
| key | description |
|
||||
| -------------|-------------|
|
||||
|
|
@ -265,10 +300,11 @@
|
|||
(let [{:keys [router] :as opts} (meta-merge default-router-options opts)
|
||||
routes (resolve-routes data opts)
|
||||
conflicting (conflicting-routes routes)
|
||||
wilds? (some impl/wild-route? routes)
|
||||
wilds? (boolean (some impl/wild-route? routes))
|
||||
all-wilds? (every? impl/wild-route? routes)
|
||||
router (cond
|
||||
router router
|
||||
(and (= 1 (count routes)) (not wilds?)) fast-router
|
||||
(not wilds?) lookup-router
|
||||
all-wilds? linear-router
|
||||
(not conflicting) mixed-router
|
||||
|
|
|
|||
|
|
@ -70,6 +70,44 @@
|
|||
(r/resolve-routes
|
||||
["/api/:version/ping"] {})))))))
|
||||
|
||||
(testing "fast-router"
|
||||
(let [router (r/router ["/api" ["/ipa" ["/large" ::beer]]])]
|
||||
(is (= :fast-router (r/router-name router)))
|
||||
(is (= [["/api/ipa/large" {:name ::beer} nil]]
|
||||
(r/routes router)))
|
||||
(is (= true (map? (r/options router))))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/large"
|
||||
:meta {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {}})
|
||||
(r/match-by-path router "/api/ipa/large")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/large"
|
||||
:meta {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size "large"})))
|
||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||
(is (= [::beer] (r/route-names router)))
|
||||
|
||||
(testing "can't be created with wildcard routes"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#":fast-router requires exactly 1 static route"
|
||||
(r/fast-router
|
||||
(r/resolve-routes
|
||||
["/api/:version/ping"] {})))))
|
||||
|
||||
(testing "can't be created with multiple routes"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#":fast-router requires exactly 1 static route"
|
||||
(r/fast-router
|
||||
(r/resolve-routes
|
||||
[["/ping"]
|
||||
["/pong"]] {})))))))
|
||||
|
||||
(testing "route coercion & compilation"
|
||||
|
||||
(testing "custom compile"
|
||||
|
|
|
|||
Loading…
Reference in a new issue