From ebbbf429eefb5775b3ef5cc0b0a3e3c4aa706454 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Mon, 13 Nov 2017 07:25:22 +0200 Subject: [PATCH] Rewrite performance.md --- doc/images/lupapiste.png | Bin 0 -> 26044 bytes doc/images/opensensors.png | Bin 0 -> 29958 bytes doc/performance.md | 74 +++++++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 doc/images/lupapiste.png create mode 100644 doc/images/opensensors.png diff --git a/doc/images/lupapiste.png b/doc/images/lupapiste.png new file mode 100644 index 0000000000000000000000000000000000000000..ff60e91d1297dfa29b0d83474b17202f6d3e7292 GIT binary patch literal 26044 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 B;A;Q? literal 0 HcmV?d00001 diff --git a/doc/images/opensensors.png b/doc/images/opensensors.png new file mode 100644 index 0000000000000000000000000000000000000000..d59d6dab965bb85c9b746ac394deeafd36b481de GIT binary patch literal 29958 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
V?Mx8zW~%5Mu{mf0;vIf~-E|@iljFaPYz36F$R6 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 z zCbU1`YAnQu$XV^<=o!(*GSjN@rEQJ3XKB(y)9Oo9dtaaPp4l4WuCSCbO=tIXHWd3f zL4BkBafKaq{8msrFV42u%3P!X{QkYR6Zdr7F%iUkn@a z8bY6@9gL5xC_nL~>hN^_k_#*rogPfwyjF8`oH8QfpOBf*;*#N#54)Q`wHeyGW{P-9 zhHW25bv9w zr1zRv6nHACq^f07e6;+M!HcT=Vp?&7naLxo{V5zSI%>}oxao(>PaibBF+?iL6o{J! zdFhCspcBEO8N>^N56=$^7u6QV7q?M!cSJ_^&c_z>8@|EwO?C#|80RAqbhs7>u||kq z--iWBRC;r0>y$w9`^{DU!M4a2a;2zBt4NkLwE_O2lienActwl=BY(+XrA$Tb3pji*Qb7FUO$gtQx!p)jz!kQqjI z=KX%9EX&8nFO+Y(jvRk<1OfZ}jz=|Uvgka-ZO2t1)!_Jn^R!>WW2AD!NzA&1ajQMt z*8&Qgkc$(pdT+c@;{_4eVe+TXkJ48gNKs8uVDjZzbkJ?D&jRjwzuXy+RIdVfvk)md zj%2wZ55CB2KNEzbsoX3uyS6~Zu_ePbT=i9T=$@S_^>fGTIbR09ep7^hp#Zl+WO0i` zzjtS!Y_fIlTrWx^PWmGx=yha-x}v$!o5NjpQ372@mtRbnbXUZ3u_=^ySDb&<$735y z*-2y3iDw@f3R~_UbhvDBtE159T;sZuTP^M9)Mm+M2oE=&h&WHshm~2iUB3?4dw>e^;@DciO(anEZcHYVOUEQJn0m+Z_21-h;{Ev3G z%O!QpEZ^V5)6CdX_gLB4Pkp!Be0lu=+Z)OV*U5pVD8w;x;y6Yt+f&&~)tY3Vrdi2# zvE-h%k;~Zz$Ns^A&$jGRZ1K9!dtXU^)Jp&1?V;PVeJUwU8v8SVoqkJh3e8wC+enF208zPJU}iV@6QfjnGKv=64)SkX_~%~vokY0OX@+( zt8WI;t{kZ5Z%MWAL?JBurQy{ac-nYH{cs6KbEv~|T^=JB4hh1(<*!B0{7?!Hc8B7Pv!WH)FWJQK0 zQ|^%XPTvbS>lCQ7X>ozERDYJi*wZ*HS7cydawI_3y$wGk@o7N3c$9kfuyBDgUwiml zgn77+w?IN!P*%F1+}!;mMu;1Aa{1fUTw%$c!W%kKMtnX2n#OAI4;lcP_L=&x9= z)AkA6wQD*_tsx=?Ij#8O29t*xBlre&#yzzQnH5ZPOg;U~_q#%$k=u+t5sPs_h2 z!cLAUh5h3mwk>u?C9IO?h~J7c2Q=^lr~w>D+}jmt`+;b02mdle0+ZM5>*87(!!f2a zwEi}GfeF3tY`^mf0cyCBsE{hTplA8h3~U#pS3eeeTVYgayw#4G!ue%L-= z+?a~S_-%{8le2Fn{?K59;64vN!0#I!(mHULS>5UrguCT;m(iMV pnV*$X{r779|L^=y`Fz 312M ops/sec +;; Execution time mean (per 1000) : 3.2 µs -> 312M ops/sec (cc/quick-bench (dotimes [_ 1000] (r/match-by-path routes "/auth/login"))) -;; Execution time mean : 530 µs -> 1.9M ops/sec +;; Execution time mean (per 1000): 530 µs -> 1.9M ops/sec (cc/quick-bench (dotimes [_ 1000] (r/match-by-path routes "/workspace/1/1"))) ``` -### Is that good? +Based on the [perf tests](https://github.com/metosin/reitit/tree/master/perf-test/clj/reitit/perf/bide_perf_test.clj), the first (static path) lookup is 300-500x faster and the second (wildcard path) lookup is 4-24x faster that the other tested routing libs (Ataraxy, Bidi, Compojure and Pedestal). -Based on some [quick perf tests](https://github.com/metosin/reitit/tree/master/perf-test/clj/reitit), the first (static path) lookup is 300-500x faster and the second (wildcard path) lookup is 4-24x faster that the other tested routing libs (ataraxy, bidi, compojure and pedestal). +But, the example is too simple for any real benchmark. Also, some of the libraries always match on the `:request-method` too and by doing so, do more work than just match by path. -But, one shoudn't trust the benchmarks. Many libraries (here: compojure, pedestal and ataraxy) always match also on the request-method so they do more work. Also, real-life routing tables might look different and different libs might behave differently. +So, we need to test something more realistic. -But, the perf should be good. +### RESTful apis -### Value of perf tests? +To get better view on the real life routing performance, there is [test](https://github.com/metosin/reitit/blob/master/perf-test/clj/reitit/opensensors_perf_test.clj) of a mid-size rest(ish) http api with 50+ routes, having a lot of path parameters. The route definitions are pulled off from the [OpenSensors](https://opensensors.io/) swagger definitions. -Real value of perf tests is to get a internal baseline to optimize against. Also, to ensure that new features don't regress the performance. +Thanks to the [prefix-tree](https://en.wikipedia.org/wiki/Radix_tree) algorithm, `reitit-ring` and Pedestal are fastest here. -It might be interesting to look out of the box and compare the fast Clojure routing libs to routers in other languages, like the [routers in Go](https://github.com/julienschmidt/go-http-routing-benchmark). +![Opensensors perf test](images/opensensors.png) -### Performance guides +### CQRS apis + +Another real-life [test scenario](https://github.com/metosin/reitit/blob/master/perf-test/clj/reitit/lupapiste_perf_test.clj) is a [CQRS](https://martinfowler.com/bliki/CQRS.html)-style route tree, where all the paths are static, e.g. `/api/command/add-order`. The route definitions are pulled out from [Lupapiste](https://github.com/lupapiste/lupapiste). The test consists of ~300 static routes (just the commands here, there would be ~200 queries too). + +Again, both `reitit-ring` and Pedestal shine here, thanks to the fast lookup-routers. On average, they are two orders of magnitude faster and on best/worst case, three orders of magnitude faster than the other tested libs. Ataraxy failed this test on `Method code too large` error. + +![Opensensors perf test](images/lupapiste.png) + +**NOTE**: If there would be even one wildcard route in the route-tree, Pedestal would fallback from lookup-router to the prefix-tree router, yielding constant, but order of magnitude slower perf. Reitit instead fallbacks to `:mixed-router`, still serving the static routes with lookup-router, just the wildcard route(s) with prefix-tree. So, the performance would not notably degrade. + +### Why measure? + +The routing perf needs to be measured to get an internal baseline to optimize against. We also want to ensure that new features don't regress the performance. Perf tests should be run in a stable CI environment. Help welcome. + +### Looking out of the box? + +It might be interesting to compare reitit with the routers in other languages, like the [routers in Go](https://github.com/julienschmidt/go-http-routing-benchmark). + +### Performance tips Few things that have an effect on performance: * Wildcard-routes are an order of magnitude slower than static routes * It's ok to mix non-wildcard and wildcard routes in a same routing tree as long as you don't disable the [conflict resolution](basics/route_conflicts.md) => if no conflicting routes are found, a `:mixed-router` can be created, which internally has a fast static path router and a separate wildcard-router. So, the static paths are still fast. * Move computation from request processing time into creation time, using by compiling [middleware](ring/compiling_middleware.md) & [route data](advanced/configuring_routers.md). + * Unmounted middleware (or interceptor) is infinitely faster than a mounted one effectively doing nothing.