mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 16:31:11 +00:00
Faster params in Trie
This commit is contained in:
parent
68d68402d9
commit
1326d76936
3 changed files with 33 additions and 17 deletions
|
|
@ -38,20 +38,35 @@ public class Trie {
|
||||||
return decode(new String(chars, begin, end - begin), hasPercent, hasPlus);
|
return decode(new String(chars, begin, end - begin), hasPercent, hasPlus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Match {
|
public static final class Match {
|
||||||
public IPersistentMap params;
|
final private Object[] params;
|
||||||
public final Object data;
|
public final Object data;
|
||||||
|
private int i = 0;
|
||||||
|
|
||||||
public Match(IPersistentMap params, Object data) {
|
public Match(Integer size, Object data) {
|
||||||
this.params = params;
|
this.params = new Object[size];
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assoc(Keyword key, Object value) {
|
||||||
|
params[i] = key;
|
||||||
|
params[i + 1] = value;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPersistentMap params() {
|
||||||
|
return new PersistentArrayMap(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
Match copy() {
|
||||||
|
return new Match(params.length, data);
|
||||||
|
}
|
||||||
|
|
||||||
@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());
|
||||||
return m.toString();
|
return m.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,13 +131,13 @@ public class Trie {
|
||||||
private final Match match;
|
private final Match match;
|
||||||
|
|
||||||
DataMatcher(IPersistentMap params, Object data) {
|
DataMatcher(IPersistentMap params, Object data) {
|
||||||
this.match = new Match(params, data);
|
this.match = new Match(params.count() * 2, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Match match(int i, int max, char[] path) {
|
public Match match(int i, int max, char[] path) {
|
||||||
if (i == max) {
|
if (i == max) {
|
||||||
return match;
|
return match.copy();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +190,7 @@ public class Trie {
|
||||||
}
|
}
|
||||||
final Match m = child.match(stop, max, path);
|
final Match m = child.match(stop, max, path);
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
m.params = m.params.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus));
|
m.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus));
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
@ -204,19 +219,18 @@ public class Trie {
|
||||||
|
|
||||||
static final class CatchAllMatcher implements Matcher {
|
static final class CatchAllMatcher implements Matcher {
|
||||||
private final Keyword parameter;
|
private final Keyword parameter;
|
||||||
private final IPersistentMap params;
|
private final Match match;
|
||||||
private final Object data;
|
|
||||||
|
|
||||||
CatchAllMatcher(Keyword parameter, IPersistentMap params, Object data) {
|
CatchAllMatcher(Keyword parameter, IPersistentMap params, Object data) {
|
||||||
|
this.match = new Match(params.count() * 2, data);
|
||||||
this.parameter = parameter;
|
this.parameter = parameter;
|
||||||
this.params = params;
|
|
||||||
this.data = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Match match(int i, int max, char[] path) {
|
public Match match(int i, int max, char[] path) {
|
||||||
if (i <= max) {
|
if (i <= max) {
|
||||||
return new Match(params.assoc(parameter, decode(path, i, max)), data);
|
match.copy().assoc(parameter, decode(path, i, max));
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +247,7 @@ public class Trie {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[" + parameter + " " + new DataMatcher(null, data) + "]";
|
return "[" + parameter + " " + new DataMatcher(null, match.data) + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,8 +296,7 @@
|
||||||
(def app
|
(def app
|
||||||
(ring/ring-handler
|
(ring/ring-handler
|
||||||
(ring/router
|
(ring/router
|
||||||
(reduce (partial add h) [] routes)
|
(reduce (partial add h) [] routes))
|
||||||
{::trie/parameters trie/record-parameters})
|
|
||||||
(ring/create-default-handler)
|
(ring/create-default-handler)
|
||||||
{:inject-match? false, :inject-router? false}))
|
{:inject-match? false, :inject-router? false}))
|
||||||
|
|
||||||
|
|
@ -319,6 +318,7 @@
|
||||||
;; 140µs (java-segment-router)
|
;; 140µs (java-segment-router)
|
||||||
;; 60ns (java-segment-router, no injects)
|
;; 60ns (java-segment-router, no injects)
|
||||||
;; 55ns (trie-router, no injects)
|
;; 55ns (trie-router, no injects)
|
||||||
|
;; 54µs (trie-router, quick-pam)
|
||||||
;; 54ns (trie-router, no injects, optimized)
|
;; 54ns (trie-router, no injects, optimized)
|
||||||
(let [req (map->Req {:request-method :get, :uri "/user/repos"})]
|
(let [req (map->Req {:request-method :get, :uri "/user/repos"})]
|
||||||
(title "static")
|
(title "static")
|
||||||
|
|
@ -337,6 +337,7 @@
|
||||||
;; 273ns (trie-router, no injects, direct-data)
|
;; 273ns (trie-router, no injects, direct-data)
|
||||||
;; 256ns (trie-router, pre-defined parameters)
|
;; 256ns (trie-router, pre-defined parameters)
|
||||||
;; 237ns (trie-router, single-sweep wild-params)
|
;; 237ns (trie-router, single-sweep wild-params)
|
||||||
|
;; 226µs (trie-router, quick-pam)
|
||||||
;; 191ns (trie-router, record parameters)
|
;; 191ns (trie-router, record parameters)
|
||||||
(let [req (map->Req {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"})]
|
(let [req (map->Req {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"})]
|
||||||
(title "param")
|
(title "param")
|
||||||
|
|
@ -354,6 +355,7 @@
|
||||||
;; 63µs (trie-router, no injects, switch-case) - 124µs (clojure)
|
;; 63µs (trie-router, no injects, switch-case) - 124µs (clojure)
|
||||||
;; 63µs (trie-router, no injects, direct-data)
|
;; 63µs (trie-router, no injects, direct-data)
|
||||||
;; 54µs (trie-router, non-transient params)
|
;; 54µs (trie-router, non-transient params)
|
||||||
|
;; 50µs (trie-router, quick-pam)
|
||||||
;; 49µs (trie-router, pre-defined parameters)
|
;; 49µs (trie-router, pre-defined parameters)
|
||||||
(let [requests (mapv route->req routes)]
|
(let [requests (mapv route->req routes)]
|
||||||
(title "all")
|
(title "all")
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
|
|
||||||
:java-source-paths ["modules/reitit-core/java-src"]
|
:java-source-paths ["modules/reitit-core/java-src"]
|
||||||
|
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.1-beta2"]
|
||||||
[org.clojure/clojurescript "1.10.520"]
|
[org.clojure/clojurescript "1.10.520"]
|
||||||
|
|
||||||
;; modules dependencies
|
;; modules dependencies
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue