mirror of
https://github.com/metosin/reitit.git
synced 2025-12-16 16:01:11 +00:00
Better perf with transient parameters
This commit is contained in:
parent
f2d131a897
commit
fe0ea19e31
5 changed files with 39 additions and 13 deletions
|
|
@ -2,7 +2,10 @@ 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;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
|
@ -22,14 +25,18 @@ public class Trie {
|
|||
}
|
||||
|
||||
public static class Match {
|
||||
public final List<Object> params = new ArrayList<>();
|
||||
final ITransientMap params = PersistentArrayMap.EMPTY.asTransient();
|
||||
public Object data;
|
||||
|
||||
public IPersistentMap parameters() {
|
||||
return params.persistent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Map<Object, Object> m = new HashMap<>();
|
||||
m.put(Keyword.intern("data"), data);
|
||||
m.put(Keyword.intern("params"), params);
|
||||
m.put(Keyword.intern("params"), params.persistent());
|
||||
return m.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -132,8 +139,7 @@ public class Trie {
|
|||
if (value[j] == '/') {
|
||||
final Match m = child.match(j, path, match);
|
||||
if (m != null) {
|
||||
m.params.add(key);
|
||||
m.params.add(decode(value, i, j - i, hasPercent, hasPlus));
|
||||
m.params.assoc(key, decode(value, i, j - i, hasPercent, hasPlus));
|
||||
}
|
||||
return m;
|
||||
} else if (value[j] == '%') {
|
||||
|
|
@ -142,12 +148,11 @@ public class Trie {
|
|||
hasPlus = true;
|
||||
}
|
||||
}
|
||||
if (child instanceof DataMatcher) {
|
||||
final Match m = child.match(path.size, path, match);
|
||||
m.params.add(key);
|
||||
m.params.add(decode(value, i, path.size - i, hasPercent, hasPlus));
|
||||
return m;
|
||||
final Match m = child.match(path.size, path, match);
|
||||
if (m != null) {
|
||||
m.params.assoc(key, decode(value, i, path.size - i, hasPercent, hasPlus));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
(:require [meta-merge.core :refer [meta-merge]]
|
||||
[clojure.string :as str]
|
||||
[reitit.segment :as segment]
|
||||
[reitit.segment :as trie]
|
||||
[reitit.trie :as trie]
|
||||
[reitit.impl :as impl #?@(:cljs [:refer [Route]])])
|
||||
#?(:clj
|
||||
(:import (reitit.impl Route))))
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
(defn lookup [^Trie$Matcher matcher path]
|
||||
(if-let [match ^Trie$Match (Trie/lookup matcher ^String path)]
|
||||
(->Match (.data match) (clojure.lang.PersistentHashMap/create (.toArray (.params match))))))
|
||||
(->Match (.data match) (.parameters match))))
|
||||
|
||||
;;
|
||||
;; matcher
|
||||
|
|
|
|||
|
|
@ -568,6 +568,7 @@
|
|||
;; 662ns (prefix-tree-router)
|
||||
;; 567ns (segment-router)
|
||||
;; 326ns (java-segment-router)
|
||||
;; 194ms (trie)
|
||||
(b! "reitit" reitit-f)
|
||||
|
||||
;; 2845ns
|
||||
|
|
@ -578,10 +579,12 @@
|
|||
;; 806ns (decode path-parameters)
|
||||
;; 735ns (maybe-map-values)
|
||||
;; 474ns (java-segment-router)
|
||||
#_(b! "reitit-ring" reitit-ring-f)
|
||||
;; 373ms (trie)
|
||||
(b! "reitit-ring" reitit-ring-f)
|
||||
|
||||
;; 385ns (java-segment-router, no injects)
|
||||
#_(b! "reitit-ring-fast" reitit-ring-fast-f)
|
||||
;; 271ms (trie)
|
||||
(b! "reitit-ring-fast" reitit-ring-fast-f)
|
||||
|
||||
;; 2553ns (linear-router)
|
||||
;; 630ns (segment-router-backed)
|
||||
|
|
@ -611,3 +614,19 @@
|
|||
(comment
|
||||
(bench-rest!))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(require '[clj-async-profiler.core :as prof])
|
||||
|
||||
(comment
|
||||
;; 629ms (arraylist)
|
||||
;; 395ns (transient)
|
||||
(let [app (ring/ring-handler (ring/router opensensors-routes))]
|
||||
(doseq [[p r] (-> app (ring/get-router) (r/routes))]
|
||||
(when-not (app {:uri p, :request-method :get})
|
||||
(println "FAIL:" p)))
|
||||
(println (app {:uri "/v1/users/1/devices/1", :request-method :get}))
|
||||
(prof/start {})
|
||||
(dotimes [_ 100000]
|
||||
(app {:uri "/v1/users/1/devices/1", :request-method :get}))
|
||||
(str (prof/stop {}))))
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@
|
|||
[manifold "0.1.8"]
|
||||
[funcool/promesa "1.9.0"]
|
||||
|
||||
[com.clojure-goes-fast/clj-async-profiler "0.2.2"]
|
||||
|
||||
;; https://github.com/bensu/doo/issues/180
|
||||
[fipp "0.6.14" :exclusions [org.clojure/core.rrb-vector]]]}
|
||||
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
|
||||
|
|
|
|||
Loading…
Reference in a new issue