diff --git a/advanced/composing_routers.html b/advanced/composing_routers.html
index 3395eb5d..8456246b 100644
--- a/advanced/composing_routers.html
+++ b/advanced/composing_routers.html
@@ -1137,7 +1137,7 @@
diff --git a/advanced/configuring_routers.html b/advanced/configuring_routers.html
index 078f8acd..01823e87 100644
--- a/advanced/configuring_routers.html
+++ b/advanced/configuring_routers.html
@@ -843,7 +843,7 @@
diff --git a/advanced/dev_workflow.html b/advanced/dev_workflow.html
index 13ddfa50..54ae8882 100644
--- a/advanced/dev_workflow.html
+++ b/advanced/dev_workflow.html
@@ -902,7 +902,7 @@
diff --git a/advanced/different_routers.html b/advanced/different_routers.html
index 84147841..15742394 100644
--- a/advanced/different_routers.html
+++ b/advanced/different_routers.html
@@ -850,7 +850,7 @@
diff --git a/advanced/route_validation.html b/advanced/route_validation.html
index d5b69295..72188bba 100644
--- a/advanced/route_validation.html
+++ b/advanced/route_validation.html
@@ -938,7 +938,7 @@
diff --git a/advanced/shared_routes.html b/advanced/shared_routes.html
index 69d9b093..361c8462 100644
--- a/advanced/shared_routes.html
+++ b/advanced/shared_routes.html
@@ -858,7 +858,7 @@
diff --git a/basics/name_based_routing.html b/basics/name_based_routing.html
index 93183448..43cfe367 100644
--- a/basics/name_based_routing.html
+++ b/basics/name_based_routing.html
@@ -861,7 +861,7 @@
diff --git a/basics/path_based_routing.html b/basics/path_based_routing.html
index 1f2f63e2..2113b941 100644
--- a/basics/path_based_routing.html
+++ b/basics/path_based_routing.html
@@ -819,7 +819,7 @@
diff --git a/basics/route_conflicts.html b/basics/route_conflicts.html
index 348737e1..b68f7a7e 100644
--- a/basics/route_conflicts.html
+++ b/basics/route_conflicts.html
@@ -862,7 +862,7 @@
diff --git a/basics/route_data.html b/basics/route_data.html
index fabd1cab..5ae93947 100644
--- a/basics/route_data.html
+++ b/basics/route_data.html
@@ -860,7 +860,7 @@
diff --git a/basics/route_data_validation.html b/basics/route_data_validation.html
index 5cb206e7..2b27d0bb 100644
--- a/basics/route_data_validation.html
+++ b/basics/route_data_validation.html
@@ -912,7 +912,7 @@
diff --git a/basics/route_syntax.html b/basics/route_syntax.html
index e29e7076..2b3f7693 100644
--- a/basics/route_syntax.html
+++ b/basics/route_syntax.html
@@ -849,7 +849,7 @@ E.g., /foo bar should be /foo%20bar.
Reitit tries to be both great in features and be really, really fast. Originally the routing was ported from Pedestal, but has been mostly rewritten.
+Besides having great features, goal of reitit is to be really, really fast. The routing was originally exported from Pedestal, but since rewritten.

Based on the perf tests, the first (static path) lookup is 300-500x faster and the second (wildcard path) lookup is 4-24x faster that the other tested routing libs (Ataraxy, Bidi, Compojure and Pedestal).
+Based on the perf tests, the first (static path) lookup is 300-500x faster and the second (wildcard path) lookup is 6-40x faster that the other tested routing libs (Ataraxy, Bidi, Compojure and Pedestal).
But, the example is too simple for any real benchmark. Also, some of the libraries always match on the :request-method too and by doing so, do more work than just match by path. Compojure does most work also by invoking the handler.
So, we need to test something more realistic.
To get better view on the real life routing performance, there is test of a mid-size rest(ish) http api with 50+ routes, having a lot of path parameters. The route definitions are pulled off from the OpenSensors swagger definitions.
-Thanks to the snappy new segment-tree algorithm, reitit-ring is fastest here. Pedestal is also fast with it's prefix-tree implementation.
Thanks to the snappy SegmentTrie (a modification of Radix Tree), reitit-ring is fastest here. Calfpath and Pedestal are also quite fast.

Another real-life test scenario is a CQRS-style route tree, where all the paths are static, e.g. /api/command/add-order. The 300 route definitions are pulled out from Lupapiste.
Another real-life test scenario is a CQRS style route tree, where all the paths are static, e.g. /api/command/add-order. The 300 route definitions are pulled out from Lupapiste.
Both reitit-ring and Pedestal shine in this test, thanks to the fast lookup-routers. On average, they are two and on best case, three orders of magnitude faster than the other tested libs. Ataraxy failed this test on Method code too large! error.

NOTE: in real life, there are usually always also wild-card routes present. In this case, Pedestal would fallback from lookup-router to the prefix-tree router, which is order of magnitude slower (30x in this test). Reitit would handle this nicely thanks to it's :mixed-router: all static routes would still be served with :lookup-router, just the wildcard routes with :segment-tree. The performance would not notably degrade.
The reitit routing perf is measured to get an internal baseline to optimize against. We also want to ensure that new features don't regress the performance. Perf tests should be run in a stable CI environment. Help welcome!
A quick poke to routers in Go indicates that the reitit is only few times slower than the fastest routers in Go. Which is really awesome (if true).
+A quick poke to routers in Go indicates that the reitit is only few times slower than the fastest routers in Go. Which is kinda awesome.
+By default, reitit.ring/ring-router, reitit.http/ring-router and reitit.http/routing-interceptor inject both Match and Router into the request. You can remove the injections setting options :inject-match? and :inject-router? to false. This saves some tens of nanos (with the hw described above).
(require '[reitit.ring :as ring])
+(require '[criterium.core :as cc])
+
+(defn create [options]
+ (ring/ring-handler
+ (ring/router
+ ["/ping" (constantly {:status 200, :body "ok"})])
+ (ring/create-default-handler)
+ options))
+
+;; 130ns
+(let [app (create nil)]
+ (cc/quick-bench
+ (app {:request-method :get, :uri "/ping"})))
+
+;; 80ns
+(let [app (create {:inject-router? false, :inject-match? false})]
+ (cc/quick-bench
+ (app {:request-method :get, :uri "/ping"})))
+
+NOTE: Without Router, you can't to do reverse routing and without Match you can't write dynamic extensions.
Few things that have an effect on performance:
:mixed-router can be created, which internally has a fast static path router and a separate wildcard-router. So, the static paths are still fast.:middleware:inject-match?match into request under :reitit.core/match key (default true):inject-router?router into request under :reitit.core/router key (default true)Simple Ring app:
@@ -961,7 +969,7 @@ diff --git a/ring/route_data_validation.html b/ring/route_data_validation.html index c2172d73..69f4b9e9 100644 --- a/ring/route_data_validation.html +++ b/ring/route_data_validation.html @@ -1037,7 +1037,7 @@ diff --git a/ring/slash_handler.html b/ring/slash_handler.html index e7a54ab8..762d4231 100644 --- a/ring/slash_handler.html +++ b/ring/slash_handler.html @@ -863,7 +863,7 @@ diff --git a/ring/static.html b/ring/static.html index e516c1fa..5b5ab1f6 100644 --- a/ring/static.html +++ b/ring/static.html @@ -865,7 +865,7 @@ diff --git a/ring/swagger.html b/ring/swagger.html index 040c4f99..4e13919a 100644 --- a/ring/swagger.html +++ b/ring/swagger.html @@ -1084,7 +1084,7 @@ see the next example