diff --git a/modules/reitit-core/java-src/reitit/Trie.java b/modules/reitit-core/java-src/reitit/Trie.java index 738a9516..515cf039 100644 --- a/modules/reitit-core/java-src/reitit/Trie.java +++ b/modules/reitit-core/java-src/reitit/Trie.java @@ -3,7 +3,6 @@ package reitit; // https://www.codeproject.com/Tips/1190293/Iteration-Over-Java-Collections-with-High-Performa import clojure.lang.IPersistentMap; -import clojure.lang.ITransientMap; import clojure.lang.Keyword; import clojure.lang.PersistentArrayMap; @@ -35,26 +34,20 @@ public class Trie { case '+': hasPlus = true; break; - default: - break; } } return decode(chars, begin, end, hasPercent, hasPlus); } public static class Match { - final ITransientMap params = PersistentArrayMap.EMPTY.asTransient(); + public IPersistentMap params = PersistentArrayMap.EMPTY; public Object data; - public IPersistentMap parameters() { - return params.persistent(); - } - @Override public String toString() { Map m = new HashMap<>(); m.put(Keyword.intern("data"), data); - m.put(Keyword.intern("params"), parameters()); + m.put(Keyword.intern("params"), params); return m.toString(); } } @@ -165,8 +158,6 @@ public class Trie { @Override public Match match(int i, int max, char[] path, Match match) { if (i < max && path[i] != end) { - boolean hasPercent = false; - boolean hasPlus = false; int stop = max; for (int j = i; j < max; j++) { final char c = path[j]; @@ -174,12 +165,10 @@ public class Trie { stop = j; break; } - hasPercent = hasPercent || c == '%'; - hasPlus = hasPlus || c == '+'; } final Match m = child.match(stop, max, path, match); if (m != null) { - m.params.assoc(key, decode(path, i, stop, hasPercent, hasPlus)); + m.params = m.params.assoc(key, decode(path, i, stop)); } return m; } @@ -218,7 +207,7 @@ public class Trie { @Override public Match match(int i, int max, char[] path, Match match) { if (i < max) { - match.params.assoc(parameter, decode(path, i, max)); + match.params = match.params.assoc(parameter, decode(path, i, max)); match.data = data; return match; } diff --git a/modules/reitit-core/src/reitit/trie.cljc b/modules/reitit-core/src/reitit/trie.cljc index 645c64df..c7f83269 100644 --- a/modules/reitit-core/src/reitit/trie.cljc +++ b/modules/reitit-core/src/reitit/trie.cljc @@ -226,7 +226,7 @@ (defn lookup [matcher path] #?(:clj (if-let [match ^Trie$Match (Trie/lookup ^Trie$Matcher matcher ^String path)] - (->Match (.data match) (.parameters match))) + (->Match (.data match) (.params match))) :cljs (if-let [match (match matcher 0 (count path) path)] (let [params (if-let [path-params (:path-params match)] (persistent! path-params) diff --git a/perf-test/clj/reitit/go_perf_test.clj b/perf-test/clj/reitit/go_perf_test.clj index 36d5d3b9..5f49558b 100644 --- a/perf-test/clj/reitit/go_perf_test.clj +++ b/perf-test/clj/reitit/go_perf_test.clj @@ -348,6 +348,7 @@ ;; 64µs (trie-router, no injects, optimized) - 124µs (clojure) ;; 63µs (trie-router, no injects, switch-case) - 124µs (clojure) ;; 63ns (trie-router, no injects, direct-data) + ;; 54ns (trie-router, non-transient params) (let [requests (mapv route->req routes)] (title "all") (cc/quick-bench diff --git a/perf-test/clj/reitit/opensensors_perf_test.clj b/perf-test/clj/reitit/opensensors_perf_test.clj index 36e02fe0..d74a9764 100644 --- a/perf-test/clj/reitit/opensensors_perf_test.clj +++ b/perf-test/clj/reitit/opensensors_perf_test.clj @@ -572,6 +572,7 @@ ;; 326ns (java-segment-router) ;; 194ns (trie) ;; 160ns (trie, prioritized) + ;; 130ns (trie, non-transient, direct-data) (b! "reitit" reitit-f) ;; 2845ns @@ -585,16 +586,18 @@ ;; 373ns (trie) ;; 323ns (trie, prioritized) ;; 289ns (trie, prioritized, zero-copy) + ;; 266ns (trie, non-transient, direct-data) (b! "reitit-ring" reitit-ring-f) ;; 385ns (java-segment-router, no injects) ;; 271ms (trie) ;; 240ns (trie, prioritized) + ;; 214ns (trie, non-transient, direct-data) (b! "reitit-ring-fast" reitit-ring-fast-f) - ;; 240ns (trie, prioritized, zero-copy) ;; 2553ns (linear-router) ;; 630ns (segment-router-backed) + ;; 464ns (trie, non-transient, direct-data) (b! "reitit-ring-linear" reitit-ring-linear-f) ;; 2137ns @@ -627,6 +630,7 @@ ;; 629ms (arraylist) ;; 409ns (transient) ;; 409ns (staticMultiMatcher) + ;; 305ns (non-persistent-params) (let [app (ring/ring-handler (ring/router opensensors-routes) {:inject-match? false, :inject-router? false}) request {:uri "/v1/users/1/devices/1", :request-method :get}] (doseq [[p r] (-> app (ring/get-router) (r/routes))] @@ -638,6 +642,7 @@ (prof/start {}) ; "Elapsed time: 9183.657012 msecs" ; "Elapsed time: 8674.70132 msecs" + ; "Elapsed time: 6714.434915 msecs" (time (dotimes [_ 20000000] (app request)))