mirror of
https://github.com/metosin/reitit.git
synced 2025-12-18 08:51:12 +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
|
// 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.Keyword;
|
||||||
|
import clojure.lang.PersistentArrayMap;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
|
@ -22,14 +25,18 @@ public class Trie {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Match {
|
public static class Match {
|
||||||
public final List<Object> params = new ArrayList<>();
|
final ITransientMap params = PersistentArrayMap.EMPTY.asTransient();
|
||||||
public Object data;
|
public Object data;
|
||||||
|
|
||||||
|
public IPersistentMap parameters() {
|
||||||
|
return params.persistent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
Map<Object, Object> m = new HashMap<>();
|
Map<Object, Object> m = new HashMap<>();
|
||||||
m.put(Keyword.intern("data"), data);
|
m.put(Keyword.intern("data"), data);
|
||||||
m.put(Keyword.intern("params"), params);
|
m.put(Keyword.intern("params"), params.persistent());
|
||||||
return m.toString();
|
return m.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,8 +139,7 @@ public class Trie {
|
||||||
if (value[j] == '/') {
|
if (value[j] == '/') {
|
||||||
final Match m = child.match(j, path, match);
|
final Match m = child.match(j, path, match);
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
m.params.add(key);
|
m.params.assoc(key, decode(value, i, j - i, hasPercent, hasPlus));
|
||||||
m.params.add(decode(value, i, j - i, hasPercent, hasPlus));
|
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
} else if (value[j] == '%') {
|
} else if (value[j] == '%') {
|
||||||
|
|
@ -142,12 +148,11 @@ public class Trie {
|
||||||
hasPlus = true;
|
hasPlus = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (child instanceof DataMatcher) {
|
final Match m = child.match(path.size, path, match);
|
||||||
final Match m = child.match(path.size, path, match);
|
if (m != null) {
|
||||||
m.params.add(key);
|
m.params.assoc(key, decode(value, i, path.size - i, hasPercent, hasPlus));
|
||||||
m.params.add(decode(value, i, path.size - i, hasPercent, hasPlus));
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [meta-merge.core :refer [meta-merge]]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[reitit.segment :as segment]
|
[reitit.segment :as segment]
|
||||||
[reitit.segment :as trie]
|
[reitit.trie :as trie]
|
||||||
[reitit.impl :as impl #?@(:cljs [:refer [Route]])])
|
[reitit.impl :as impl #?@(:cljs [:refer [Route]])])
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import (reitit.impl Route))))
|
(:import (reitit.impl Route))))
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
|
|
||||||
(defn lookup [^Trie$Matcher matcher path]
|
(defn lookup [^Trie$Matcher matcher path]
|
||||||
(if-let [match ^Trie$Match (Trie/lookup matcher ^String 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
|
;; matcher
|
||||||
|
|
|
||||||
|
|
@ -568,6 +568,7 @@
|
||||||
;; 662ns (prefix-tree-router)
|
;; 662ns (prefix-tree-router)
|
||||||
;; 567ns (segment-router)
|
;; 567ns (segment-router)
|
||||||
;; 326ns (java-segment-router)
|
;; 326ns (java-segment-router)
|
||||||
|
;; 194ms (trie)
|
||||||
(b! "reitit" reitit-f)
|
(b! "reitit" reitit-f)
|
||||||
|
|
||||||
;; 2845ns
|
;; 2845ns
|
||||||
|
|
@ -578,10 +579,12 @@
|
||||||
;; 806ns (decode path-parameters)
|
;; 806ns (decode path-parameters)
|
||||||
;; 735ns (maybe-map-values)
|
;; 735ns (maybe-map-values)
|
||||||
;; 474ns (java-segment-router)
|
;; 474ns (java-segment-router)
|
||||||
#_(b! "reitit-ring" reitit-ring-f)
|
;; 373ms (trie)
|
||||||
|
(b! "reitit-ring" reitit-ring-f)
|
||||||
|
|
||||||
;; 385ns (java-segment-router, no injects)
|
;; 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)
|
;; 2553ns (linear-router)
|
||||||
;; 630ns (segment-router-backed)
|
;; 630ns (segment-router-backed)
|
||||||
|
|
@ -611,3 +614,19 @@
|
||||||
(comment
|
(comment
|
||||||
(bench-rest!))
|
(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"]
|
[manifold "0.1.8"]
|
||||||
[funcool/promesa "1.9.0"]
|
[funcool/promesa "1.9.0"]
|
||||||
|
|
||||||
|
[com.clojure-goes-fast/clj-async-profiler "0.2.2"]
|
||||||
|
|
||||||
;; https://github.com/bensu/doo/issues/180
|
;; https://github.com/bensu/doo/issues/180
|
||||||
[fipp "0.6.14" :exclusions [org.clojure/core.rrb-vector]]]}
|
[fipp "0.6.14" :exclusions [org.clojure/core.rrb-vector]]]}
|
||||||
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
|
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue