Decode in single sweep, 8% faster

This commit is contained in:
Tommi Reiman 2019-03-07 08:17:17 +02:00
parent d50da2bc85
commit 5ab1f2829e
3 changed files with 9 additions and 4 deletions

View file

@ -12,7 +12,7 @@
* `"/file-:id/topics"` (free start, ends at slash) * `"/file-:id/topics"` (free start, ends at slash)
* `"/file-{name}.html"` (free start & end) * `"/file-{name}.html"` (free start & end)
* backed by a new `:trie-router`, replacing `:segment-router` * backed by a new `:trie-router`, replacing `:segment-router`
* [over 40% faster](https://metosin.github.io/reitit/performance.html) on the JVM * [up to 2x faster](https://metosin.github.io/reitit/performance.html) on the JVM
* **BREAKING**: `reitit.spec/validate-spec!` has been renamed to `validate` * **BREAKING**: `reitit.spec/validate-spec!` has been renamed to `validate`
* With `clojure.spec` coercion, values flow through both `st/coerce` & `st/conform` yielding better error messages. Original issue in [compojure-api](https://github.com/metosin/compojure-api/issues/409). * With `clojure.spec` coercion, values flow through both `st/coerce` & `st/conform` yielding better error messages. Original issue in [compojure-api](https://github.com/metosin/compojure-api/issues/409).
@ -59,7 +59,7 @@
### `reitit-frontend` ### `reitit-frontend`
* **BREAKING**: Frontend controllers redesigned * Frontend controllers redesigned
* Controller `:params` function has been deprecated * Controller `:params` function has been deprecated
* Controller `:identity` function works the same as `:params` * Controller `:identity` function works the same as `:params`
* New `:parameters` option can be used to declare which parameters * New `:parameters` option can be used to declare which parameters

View file

@ -160,10 +160,14 @@ public class Trie {
@Override @Override
public Match match(int i, int max, char[] path) { public Match match(int i, int max, char[] path) {
boolean hasPercent = false;
boolean hasPlus = false;
if (i < max && path[i] != end) { if (i < max && path[i] != end) {
int stop = max; int stop = max;
for (int j = i; j < max; j++) { for (int j = i; j < max; j++) {
final char c = path[j]; final char c = path[j];
hasPercent = hasPercent || c == '%';
hasPlus = hasPlus || c == '+';
if (c == end) { if (c == end) {
stop = j; stop = j;
break; break;
@ -171,7 +175,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(path, i, stop)); m.params = m.params.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus));
} }
return m; return m;
} }

View file

@ -334,6 +334,7 @@
;; 277ns (trie-router, no injects, switch-case) - 690ns clojure ;; 277ns (trie-router, no injects, switch-case) - 690ns clojure
;; 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)
(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")
(assert (= {:status 200, :body "/repos/:owner/:repo/stargazers"} (app req))) (assert (= {:status 200, :body "/repos/:owner/:repo/stargazers"} (app req)))
@ -365,6 +366,6 @@
(do (do
(require '[clj-async-profiler.core :as prof]) (require '[clj-async-profiler.core :as prof])
(prof/profile (prof/profile
(dotimes [_ 1000000] (dotimes [_ 10000000]
(app {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"}))) (app {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"})))
(prof/serve-files 8080))) (prof/serve-files 8080)))