Skip to content

Commit e44017d

Browse files
das7padAlexVulaj
andauthored
perf: cut allocations (#691)
**Summary of Changes** Hello! I found a few "low hanging" allocations that can be deferred until needed or even skipped entirely. With all the optimizations combined, we can see the best improvement for simple, static routes (like a `/status` endpoint) that do not read the `Route` from the request context via `CurrentRoute` and do not populate any vars. On these routes, we can process requests with a single allocation for the `RouteMatch` object. Previously there were 9 extra allocations. For said routes the processing overhead (ns/op) in mux dropped by 75%, which is a speedup of 4x. Other routes can expect to see a double-digit percentage reduction in both processing overhead (ns/op) and allocations as well. These are driven by merging the context population into a single operation, eliminating two of ten allocations. (Eliminating that last allocation for the `RouteMatch` in the best case requires significant refactoring to maintain full backwards compatibility. Something for another day.) Each commit message contains benchmark results for showcasing particular (micro) optimizations in reduced allocations and in a few cases notable direct CPU time savings. I also ran longer benchmarks with 100 repetitions in multiple settings on different generations of (server) CPUs. First, there is the full set of benchmarks in this repository and second, the popular benchmarks https://github.com/julienschmidt/go-http-routing-benchmark. All but the last change are entirely "free", as in they do not cut features for gains in performance. The last change for omitting the `Route` from the context is behind an optional flag that users can opt in when they do not read the `Route` from the request context. Said flag is stored local in a `Router`, so users can enable/disable the flag on Subrouters individually. <details> <summary> Benchmark results </summary> I added all the new benchmarks onto a `baseline` branch for comparing the performance of the changes, tip is 0eba4f5731f329d9a95b67359e795344343a6119. I'm running these tests on "shared" compute instances (and my Laptop), so expect some noise (and frequency scaling on the i7). <details> <summary> mux project benchmarks </summary> You can reproduce these benchmarks using docker, pinned to CPU 1: ```bash docker run --rm --pull always -v /logs:/logs --cpuset-cpus 1 -d golang:1.18 bash -exc 'git clone https://github.com/das7pad/mux.git && cd mux && for branch in baseline perf-cut-allocations; do git checkout "$branch" && go test -benchmem -bench . -count 100 -timeout 1h > "/logs/$branch-all.txt"; done; go install golang.org/x/perf/cmd/benchstat@latest; benchstat /logs/baseline-all.txt /logs/perf-cut-allocations-all.txt > /logs/compare-all.txt' ``` <details> <summary> Modern Xeon E, 3.4 GHz </summary> ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz name old time/op new time/op delta Mux 1.09µs ± 5% 0.96µs ± 6% -12.33% (p=0.000 n=90+90) MuxSimple/default 654ns ± 5% 333ns ± 4% -49.06% (p=0.000 n=90+94) MuxSimple/omit_route_from_ctx 655ns ± 5% 146ns ± 3% -77.78% (p=0.000 n=93+95) MuxAlternativeInRegexp 1.58µs ± 5% 1.30µs ± 3% -17.75% (p=0.000 n=92+90) ManyPathVariables 1.82µs ± 6% 1.65µs ± 5% -9.73% (p=0.000 n=94+93) PopulateContext/no_populated_vars 665ns ± 5% 339ns ± 5% -48.97% (p=0.000 n=95+96) PopulateContext/empty_var 910ns ± 5% 763ns ± 6% -16.16% (p=0.000 n=84+87) PopulateContext/populated_vars 974ns ±10% 807ns ± 7% -17.13% (p=0.000 n=96+89) PopulateContext/omit_route_/static 664ns ± 5% 148ns ± 3% -77.66% (p=0.000 n=94+89) PopulateContext/omit_route_/dynamic 915ns ± 6% 741ns ± 6% -18.98% (p=0.000 n=90+94) _findQueryKey/0 158ns ± 2% 146ns ± 2% -7.07% (p=0.000 n=91+88) _findQueryKey/1 198ns ± 4% 196ns ± 5% -0.56% (p=0.001 n=92+95) _findQueryKey/2 710ns ± 4% 705ns ± 4% -0.80% (p=0.000 n=94+94) _findQueryKey/3 804ns ± 4% 798ns ± 5% -0.82% (p=0.000 n=90+94) _findQueryKey/4 3.85ns ± 2% 3.85ns ± 3% ~ (p=0.224 n=89+93) _findQueryKeyGoLib/0 664ns ± 4% 668ns ± 5% +0.67% (p=0.030 n=97+94) _findQueryKeyGoLib/1 359ns ± 6% 359ns ± 6% ~ (p=0.830 n=94+93) _findQueryKeyGoLib/2 2.24µs ± 3% 2.23µs ± 4% -0.37% (p=0.041 n=95+93) _findQueryKeyGoLib/3 2.94µs ± 4% 2.92µs ± 3% -0.68% (p=0.001 n=90+94) _findQueryKeyGoLib/4 3.63ns ± 4% 3.62ns ± 3% -0.38% (p=0.014 n=91+88) name old alloc/op new alloc/op delta Mux 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) MuxSimple/default 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) MuxAlternativeInRegexp 2.62kB ± 0% 1.82kB ± 0% -30.49% (p=0.000 n=100+100) ManyPathVariables 1.53kB ± 1% 1.13kB ± 0% -26.45% (p=0.000 n=99+93) PopulateContext/no_populated_vars 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) PopulateContext/empty_var 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) PopulateContext/populated_vars 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) PopulateContext/omit_route_/static 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) _findQueryKey/0 0.00B 0.00B ~ (all equal) _findQueryKey/1 40.0B ± 0% 40.0B ± 0% ~ (all equal) _findQueryKey/2 483B ± 0% 483B ± 0% ~ (all equal) _findQueryKey/3 543B ± 0% 543B ± 0% ~ (all equal) _findQueryKey/4 0.00B 0.00B ~ (all equal) _findQueryKeyGoLib/0 864B ± 0% 864B ± 0% ~ (all equal) _findQueryKeyGoLib/1 432B ± 0% 432B ± 0% ~ (all equal) _findQueryKeyGoLib/2 1.54kB ± 0% 1.54kB ± 0% ~ (all equal) _findQueryKeyGoLib/3 1.98kB ± 0% 1.98kB ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Mux 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) MuxSimple/default 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) MuxAlternativeInRegexp 20.0 ± 0% 16.0 ± 0% -20.00% (p=0.000 n=100+100) ManyPathVariables 14.0 ± 0% 12.0 ± 0% -14.29% (p=0.000 n=100+100) PopulateContext/no_populated_vars 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) PopulateContext/empty_var 11.0 ± 0% 9.0 ± 0% -18.18% (p=0.000 n=100+100) PopulateContext/populated_vars 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) PopulateContext/omit_route_/static 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 11.0 ± 0% 8.0 ± 0% -27.27% (p=0.000 n=100+100) _findQueryKey/0 0.00 0.00 ~ (all equal) _findQueryKey/1 3.00 ± 0% 3.00 ± 0% ~ (all equal) _findQueryKey/2 10.0 ± 0% 10.0 ± 0% ~ (all equal) _findQueryKey/3 11.0 ± 0% 11.0 ± 0% ~ (all equal) _findQueryKey/4 0.00 0.00 ~ (all equal) _findQueryKeyGoLib/0 8.00 ± 0% 8.00 ± 0% ~ (all equal) _findQueryKeyGoLib/1 4.00 ± 0% 4.00 ± 0% ~ (all equal) _findQueryKeyGoLib/2 24.0 ± 0% 24.0 ± 0% ~ (all equal) _findQueryKeyGoLib/3 28.0 ± 0% 28.0 ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00 0.00 ~ (all equal) ``` --- </details> <details> <summary> Older Xeon Gold, 2.3 GHz </summary> (Actual CPU identifier is rather `Intel(R) Xeon(R) Gold 5122 CPU @ 2.30GHz`) ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel Xeon Processor (Skylake, IBRS) name old time/op new time/op delta Mux 1.61µs ± 6% 1.43µs ± 6% -11.38% (p=0.000 n=97+96) MuxSimple/default 979ns ± 8% 508ns ± 7% -48.15% (p=0.000 n=93+98) MuxSimple/omit_route_from_ctx 1.00µs ±12% 0.22µs ± 4% -77.76% (p=0.000 n=99+96) MuxAlternativeInRegexp 2.40µs ± 9% 2.03µs ±12% -15.15% (p=0.000 n=94+98) ManyPathVariables 2.77µs ± 8% 2.60µs ±12% -6.17% (p=0.000 n=94+99) PopulateContext/no_populated_vars 1.03µs ±11% 0.54µs ±13% -47.57% (p=0.000 n=94+98) PopulateContext/empty_var 1.35µs ± 6% 1.23µs ±11% -9.01% (p=0.000 n=95+96) PopulateContext/populated_vars 1.40µs ± 8% 1.30µs ±14% -6.98% (p=0.000 n=97+99) PopulateContext/omit_route_/static 989ns ± 7% 239ns ±10% -75.78% (p=0.000 n=99+99) PopulateContext/omit_route_/dynamic 1.34µs ± 7% 1.21µs ±15% -10.04% (p=0.000 n=95+99) _findQueryKey/0 242ns ± 8% 228ns ± 8% -6.00% (p=0.000 n=97+95) _findQueryKey/1 304ns ± 7% 309ns ± 9% +1.60% (p=0.002 n=97+97) _findQueryKey/2 1.08µs ± 8% 1.14µs ±10% +5.28% (p=0.000 n=99+97) _findQueryKey/3 1.20µs ± 6% 1.23µs ± 9% +2.03% (p=0.000 n=92+99) _findQueryKey/4 5.86ns ± 4% 5.89ns ± 5% +0.56% (p=0.041 n=93+96) _findQueryKeyGoLib/0 992ns ± 7% 1067ns ±11% +7.59% (p=0.000 n=94+98) _findQueryKeyGoLib/1 528ns ± 6% 571ns ±11% +8.04% (p=0.000 n=97+100) _findQueryKeyGoLib/2 3.46µs ± 6% 3.60µs ±10% +4.18% (p=0.000 n=96+95) _findQueryKeyGoLib/3 4.54µs ± 6% 4.75µs ±11% +4.62% (p=0.000 n=92+98) _findQueryKeyGoLib/4 5.50ns ± 4% 5.62ns ± 7% +2.14% (p=0.000 n=91+96) name old alloc/op new alloc/op delta Mux 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) MuxSimple/default 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) MuxAlternativeInRegexp 2.62kB ± 0% 1.82kB ± 0% -30.49% (p=0.000 n=100+100) ManyPathVariables 1.52kB ± 0% 1.12kB ± 0% -26.50% (p=0.000 n=92+97) PopulateContext/no_populated_vars 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) PopulateContext/empty_var 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) PopulateContext/populated_vars 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) PopulateContext/omit_route_/static 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) _findQueryKey/0 0.00B 0.00B ~ (all equal) _findQueryKey/1 40.0B ± 0% 40.0B ± 0% ~ (all equal) _findQueryKey/2 483B ± 0% 483B ± 0% ~ (all equal) _findQueryKey/3 543B ± 0% 543B ± 0% ~ (all equal) _findQueryKey/4 0.00B 0.00B ~ (all equal) _findQueryKeyGoLib/0 864B ± 0% 864B ± 0% ~ (all equal) _findQueryKeyGoLib/1 432B ± 0% 432B ± 0% ~ (all equal) _findQueryKeyGoLib/2 1.54kB ± 0% 1.54kB ± 0% ~ (all equal) _findQueryKeyGoLib/3 1.98kB ± 0% 1.98kB ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Mux 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) MuxSimple/default 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) MuxAlternativeInRegexp 20.0 ± 0% 16.0 ± 0% -20.00% (p=0.000 n=100+100) ManyPathVariables 14.0 ± 0% 12.0 ± 0% -14.29% (p=0.000 n=100+100) PopulateContext/no_populated_vars 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) PopulateContext/empty_var 11.0 ± 0% 9.0 ± 0% -18.18% (p=0.000 n=100+100) PopulateContext/populated_vars 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) PopulateContext/omit_route_/static 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 11.0 ± 0% 8.0 ± 0% -27.27% (p=0.000 n=100+100) _findQueryKey/0 0.00 0.00 ~ (all equal) _findQueryKey/1 3.00 ± 0% 3.00 ± 0% ~ (all equal) _findQueryKey/2 10.0 ± 0% 10.0 ± 0% ~ (all equal) _findQueryKey/3 11.0 ± 0% 11.0 ± 0% ~ (all equal) _findQueryKey/4 0.00 0.00 ~ (all equal) _findQueryKeyGoLib/0 8.00 ± 0% 8.00 ± 0% ~ (all equal) _findQueryKeyGoLib/1 4.00 ± 0% 4.00 ± 0% ~ (all equal) _findQueryKeyGoLib/2 24.0 ± 0% 24.0 ± 0% ~ (all equal) _findQueryKeyGoLib/3 28.0 ± 0% 28.0 ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00 0.00 ~ (all equal) ``` --- </details> <details> <summary> Older Xeon E, 2.4 GHz </summary> ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz name old time/op new time/op delta Mux 1.81µs ±13% 1.57µs ±10% -13.50% (p=0.000 n=99+97) MuxSimple/default 1.09µs ± 8% 0.55µs ±10% -49.51% (p=0.000 n=96+95) MuxSimple/omit_route_from_ctx 1.08µs ±10% 0.25µs ± 8% -76.66% (p=0.000 n=95+94) MuxAlternativeInRegexp 2.59µs ±12% 2.14µs ±13% -17.06% (p=0.000 n=95+92) ManyPathVariables 3.11µs ± 9% 2.78µs ±10% -10.62% (p=0.000 n=96+99) PopulateContext/no_populated_vars 1.09µs ± 9% 0.56µs ± 7% -48.63% (p=0.000 n=94+93) PopulateContext/empty_var 1.48µs ± 9% 1.28µs ±12% -13.52% (p=0.000 n=97+96) PopulateContext/populated_vars 1.56µs ±11% 1.34µs ±10% -13.84% (p=0.000 n=96+97) PopulateContext/omit_route_/static 1.08µs ± 9% 0.26µs ± 9% -75.89% (p=0.000 n=98+97) PopulateContext/omit_route_/dynamic 1.50µs ±11% 1.20µs ± 9% -19.96% (p=0.000 n=94+93) _findQueryKey/0 254ns ± 8% 243ns ± 8% -4.44% (p=0.000 n=96+91) _findQueryKey/1 336ns ± 7% 336ns ± 8% ~ (p=0.920 n=96+95) _findQueryKey/2 1.25µs ±12% 1.27µs ±14% +1.55% (p=0.043 n=97+98) _findQueryKey/3 1.37µs ± 8% 1.38µs ± 9% +0.97% (p=0.030 n=97+95) _findQueryKey/4 5.93ns ± 6% 5.97ns ± 7% ~ (p=0.074 n=97+97) _findQueryKeyGoLib/0 1.07µs ± 9% 1.13µs ±10% +4.99% (p=0.000 n=96+95) _findQueryKeyGoLib/1 581ns ± 8% 586ns ± 9% ~ (p=0.089 n=96+99) _findQueryKeyGoLib/2 3.93µs ±12% 3.80µs ±10% -3.31% (p=0.000 n=96+91) _findQueryKeyGoLib/3 5.18µs ±10% 5.06µs ± 8% -2.27% (p=0.000 n=98+99) _findQueryKeyGoLib/4 6.52ns ± 6% 6.49ns ± 4% ~ (p=0.232 n=96+94) name old alloc/op new alloc/op delta Mux 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) MuxSimple/default 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) MuxAlternativeInRegexp 2.62kB ± 0% 1.82kB ± 0% -30.49% (p=0.000 n=100+100) ManyPathVariables 1.52kB ± 0% 1.12kB ± 1% -26.58% (p=0.000 n=92+96) PopulateContext/no_populated_vars 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) PopulateContext/empty_var 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) PopulateContext/populated_vars 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) PopulateContext/omit_route_/static 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) _findQueryKey/0 0.00B 0.00B ~ (all equal) _findQueryKey/1 40.0B ± 0% 40.0B ± 0% ~ (all equal) _findQueryKey/2 483B ± 0% 483B ± 0% ~ (all equal) _findQueryKey/3 543B ± 0% 543B ± 0% ~ (all equal) _findQueryKey/4 0.00B 0.00B ~ (all equal) _findQueryKeyGoLib/0 864B ± 0% 864B ± 0% ~ (all equal) _findQueryKeyGoLib/1 432B ± 0% 432B ± 0% ~ (all equal) _findQueryKeyGoLib/2 1.54kB ± 0% 1.54kB ± 0% ~ (all equal) _findQueryKeyGoLib/3 1.98kB ± 0% 1.98kB ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Mux 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) MuxSimple/default 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) MuxSimple/omit_route_from_ctx 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) MuxAlternativeInRegexp 20.0 ± 0% 16.0 ± 0% -20.00% (p=0.000 n=100+100) ManyPathVariables 14.0 ± 0% 12.0 ± 0% -14.29% (p=0.000 n=100+100) PopulateContext/no_populated_vars 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) PopulateContext/empty_var 11.0 ± 0% 9.0 ± 0% -18.18% (p=0.000 n=100+100) PopulateContext/populated_vars 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) PopulateContext/omit_route_/static 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) PopulateContext/omit_route_/dynamic 11.0 ± 0% 8.0 ± 0% -27.27% (p=0.000 n=100+100) _findQueryKey/0 0.00 0.00 ~ (all equal) _findQueryKey/1 3.00 ± 0% 3.00 ± 0% ~ (all equal) _findQueryKey/2 10.0 ± 0% 10.0 ± 0% ~ (all equal) _findQueryKey/3 11.0 ± 0% 11.0 ± 0% ~ (all equal) _findQueryKey/4 0.00 0.00 ~ (all equal) _findQueryKeyGoLib/0 8.00 ± 0% 8.00 ± 0% ~ (all equal) _findQueryKeyGoLib/1 4.00 ± 0% 4.00 ± 0% ~ (all equal) _findQueryKeyGoLib/2 24.0 ± 0% 24.0 ± 0% ~ (all equal) _findQueryKeyGoLib/3 28.0 ± 0% 28.0 ± 0% ~ (all equal) _findQueryKeyGoLib/4 0.00 0.00 ~ (all equal) ``` --- </details> --- </details> <details> <summary> Popular go-http-routing-benchmark </summary> I pushed three branches for comparison to my fork: https://github.com/das7pad/go-http-routing-benchmark - `before`, this is the baseline branch mentioned above - `after`, this is the PR revision - `after-omit-route`, like `after` with the `OmitRouteFromContext` flag enabled You can reproduce these benchmarks using docker, pinned to CPU 1: ```bash docker run --rm --pull always -v /logs:/logs --cpuset-cpus 1 -d golang:1.18 bash -exc 'git clone https://github.com/das7pad/go-http-routing-benchmark.git && cd go-http-routing-benchmark && for branch in before after after-omit-route; do git checkout "$branch" && go test -benchmem -bench Gorilla -count 100 -timeout 1h > "/logs/$branch.txt"; done; go install golang.org/x/perf/cmd/benchstat@latest; benchstat /logs/before.txt /logs/after.txt > /logs/compare-before-vs-after.txt; benchstat /logs/before.txt /logs/after-omit-route.txt > /logs/compare-before-vs-after-omit-route.txt' ``` <details> <summary> Modern Xeon E, 3.4 GHz </summary> Before vs After with omit Route flag enabled ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz name old time/op new time/op delta GorillaMux_Param 1.86µs ±13% 1.37µs ± 6% -26.08% (p=0.000 n=94+96) GorillaMux_Param5 2.61µs ± 4% 2.20µs ± 4% -15.92% (p=0.000 n=89+95) GorillaMux_Param20 6.13µs ± 3% 3.98µs ± 4% -35.07% (p=0.000 n=90+94) GorillaMux_ParamWrite 1.87µs ± 5% 1.43µs ± 8% -23.51% (p=0.000 n=95+92) GorillaMux_GithubStatic 3.77µs ± 5% 2.43µs ± 4% -35.40% (p=0.000 n=96+96) GorillaMux_GithubParam 5.68µs ± 6% 5.21µs ± 5% -8.32% (p=0.000 n=93+93) GorillaMux_GithubAll 2.86ms ± 6% 2.71ms ± 4% -5.44% (p=0.000 n=99+96) GorillaMux_GPlusStatic 1.31µs ± 5% 0.21µs ± 4% -84.29% (p=0.000 n=92+95) GorillaMux_GPlusParam 2.37µs ± 3% 1.96µs ± 2% -17.42% (p=0.000 n=96+94) GorillaMux_GPlus2Params 4.43µs ± 3% 3.90µs ± 3% -11.89% (p=0.000 n=91+90) GorillaMux_GPlusAll 37.1µs ± 6% 28.9µs ± 5% -22.26% (p=0.000 n=93+92) GorillaMux_ParseStatic 1.55µs ± 5% 0.42µs ± 4% -72.78% (p=0.000 n=95+91) GorillaMux_ParseParam 1.88µs ± 7% 1.41µs ± 7% -24.66% (p=0.000 n=94+93) GorillaMux_Parse2Params 2.21µs ± 4% 1.74µs ± 6% -21.16% (p=0.000 n=94+96) GorillaMux_ParseAll 71.8µs ± 4% 51.3µs ± 4% -28.51% (p=0.000 n=93+94) GorillaMux_StaticAll 771µs ± 4% 492µs ± 3% -36.17% (p=0.000 n=95+90) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.93kB ± 0% -32.56% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.10kB ± 0% -39.86% (p=0.000 n=100+80) GorillaMux_ParamWrite 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 149kB ± 0% -42.37% (p=0.000 n=86+99) GorillaMux_GPlusStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 9.7kB ± 0% -41.43% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 14.4kB ± 0% -53.88% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 8kB ± 0% -95.24% (p=0.000 n=100+100) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 7.0 ± 0% -41.67% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.21k ± 0% -39.57% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 79 ± 0% -38.28% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 122 ± 0% -51.20% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.16k ± 0% -88.89% (p=0.000 n=100+100) ``` Before vs After ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz name old time/op new time/op delta GorillaMux_Param 1.86µs ±13% 1.47µs ±11% -21.05% (p=0.000 n=94+93) GorillaMux_Param5 2.61µs ± 4% 2.25µs ± 2% -13.64% (p=0.000 n=89+90) GorillaMux_Param20 6.13µs ± 3% 4.05µs ± 4% -33.96% (p=0.000 n=90+91) GorillaMux_ParamWrite 1.87µs ± 5% 1.47µs ± 4% -21.03% (p=0.000 n=95+96) GorillaMux_GithubStatic 3.77µs ± 5% 3.16µs ± 3% -16.11% (p=0.000 n=96+95) GorillaMux_GithubParam 5.68µs ± 6% 5.31µs ± 6% -6.57% (p=0.000 n=93+94) GorillaMux_GithubAll 2.86ms ± 6% 2.72ms ± 4% -4.97% (p=0.000 n=99+95) GorillaMux_GPlusStatic 1.31µs ± 5% 0.66µs ± 6% -49.50% (p=0.000 n=92+95) GorillaMux_GPlusParam 2.37µs ± 3% 2.04µs ± 4% -13.87% (p=0.000 n=96+90) GorillaMux_GPlus2Params 4.43µs ± 3% 3.98µs ± 5% -10.21% (p=0.000 n=91+92) GorillaMux_GPlusAll 37.1µs ± 6% 30.6µs ± 6% -17.65% (p=0.000 n=93+94) GorillaMux_ParseStatic 1.55µs ± 5% 0.90µs ± 4% -41.88% (p=0.000 n=95+91) GorillaMux_ParseParam 1.88µs ± 7% 1.47µs ± 6% -21.53% (p=0.000 n=94+95) GorillaMux_Parse2Params 2.21µs ± 4% 1.80µs ± 5% -18.26% (p=0.000 n=94+90) GorillaMux_ParseAll 71.8µs ± 4% 57.9µs ± 3% -19.30% (p=0.000 n=93+97) GorillaMux_StaticAll 771µs ± 4% 664µs ± 4% -13.87% (p=0.000 n=95+95) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.98kB ± 0% -29.07% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.14kB ± 0% -38.48% (p=0.000 n=100+83) GorillaMux_ParamWrite 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 173kB ± 0% -33.02% (p=0.000 n=86+100) GorillaMux_GPlusStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 11.1kB ± 0% -32.82% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 19.6kB ± 0% -37.02% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 78kB ± 0% -50.79% (p=0.000 n=100+100) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 8.0 ± 0% -33.33% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.48k ± 0% -25.78% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 96 ± 0% -25.00% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 168 ± 0% -32.80% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.63k ± 0% -55.56% (p=0.000 n=100+100) ``` --- </details> <details> <summary> Older Xeon Gold, 2.3 GHz </summary> Before vs After with omit Route flag enabled (Actual CPU identifier is rather `Intel(R) Xeon(R) Gold 5122 CPU @ 2.30GHz`) ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel Xeon Processor (Skylake, IBRS) name old time/op new time/op delta GorillaMux_Param 3.02µs ±14% 2.24µs ±12% -25.60% (p=0.000 n=100+99) GorillaMux_Param5 4.20µs ±12% 3.45µs ±10% -17.84% (p=0.000 n=95+97) GorillaMux_Param20 9.86µs ±12% 6.36µs ± 9% -35.54% (p=0.000 n=96+93) GorillaMux_ParamWrite 2.97µs ± 7% 2.21µs ± 5% -25.40% (p=0.000 n=96+96) GorillaMux_GithubStatic 5.82µs ± 6% 3.62µs ± 5% -37.87% (p=0.000 n=99+98) GorillaMux_GithubParam 8.81µs ± 7% 7.90µs ± 5% -10.37% (p=0.000 n=97+95) GorillaMux_GithubAll 3.93ms ± 4% 3.62ms ± 6% -7.72% (p=0.000 n=97+99) GorillaMux_GPlusStatic 2.04µs ± 7% 0.33µs ± 9% -83.77% (p=0.000 n=98+99) GorillaMux_GPlusParam 3.72µs ± 6% 3.14µs ±13% -15.44% (p=0.000 n=99+99) GorillaMux_GPlus2Params 6.89µs ± 8% 6.57µs ± 9% -4.70% (p=0.000 n=92+98) GorillaMux_GPlusAll 56.1µs ± 6% 46.5µs ±11% -17.14% (p=0.000 n=95+98) GorillaMux_ParseStatic 2.43µs ± 6% 0.67µs ±11% -72.49% (p=0.000 n=96+99) GorillaMux_ParseParam 2.91µs ± 8% 2.29µs ±12% -21.07% (p=0.000 n=98+97) GorillaMux_Parse2Params 3.44µs ± 8% 2.84µs ± 8% -17.53% (p=0.000 n=98+95) GorillaMux_ParseAll 111µs ± 5% 80µs ±11% -27.91% (p=0.000 n=96+98) GorillaMux_StaticAll 1.13ms ± 4% 0.71ms ± 5% -37.32% (p=0.000 n=97+97) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.93kB ± 0% -32.56% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.10kB ± 0% -39.86% (p=0.000 n=100+79) GorillaMux_ParamWrite 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 149kB ± 0% -42.37% (p=0.000 n=80+96) GorillaMux_GPlusStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 9.7kB ± 0% -41.43% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 14.4kB ± 0% -53.88% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 8kB ± 0% -95.24% (p=0.000 n=100+100) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 7.0 ± 0% -41.67% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.21k ± 0% -39.57% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 79 ± 0% -38.28% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 122 ± 0% -51.20% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.16k ± 0% -88.89% (p=0.000 n=100+100) ``` Before vs After (Actual CPU identifier is rather `Intel(R) Xeon(R) Gold 5122 CPU @ 2.30GHz`) ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel Xeon Processor (Skylake, IBRS) name old time/op new time/op delta GorillaMux_Param 3.02µs ±14% 2.27µs ± 8% -24.70% (p=0.000 n=100+98) GorillaMux_Param5 4.20µs ±12% 3.48µs ± 5% -17.29% (p=0.000 n=95+98) GorillaMux_Param20 9.86µs ±12% 6.41µs ± 6% -35.05% (p=0.000 n=96+92) GorillaMux_ParamWrite 2.97µs ± 7% 2.31µs ± 6% -22.12% (p=0.000 n=96+98) GorillaMux_GithubStatic 5.82µs ± 6% 4.69µs ± 5% -19.52% (p=0.000 n=99+96) GorillaMux_GithubParam 8.81µs ± 7% 7.98µs ± 4% -9.48% (p=0.000 n=97+96) GorillaMux_GithubAll 3.93ms ± 4% 3.64ms ± 5% -7.18% (p=0.000 n=97+94) GorillaMux_GPlusStatic 2.04µs ± 7% 1.05µs ±12% -48.53% (p=0.000 n=98+94) GorillaMux_GPlusParam 3.72µs ± 6% 3.09µs ± 5% -16.76% (p=0.000 n=99+96) GorillaMux_GPlus2Params 6.89µs ± 8% 6.18µs ± 5% -10.28% (p=0.000 n=92+95) GorillaMux_GPlusAll 56.1µs ± 6% 46.0µs ± 5% -17.98% (p=0.000 n=95+93) GorillaMux_ParseStatic 2.43µs ± 6% 1.44µs ± 5% -40.52% (p=0.000 n=96+95) GorillaMux_ParseParam 2.91µs ± 8% 2.30µs ± 5% -20.93% (p=0.000 n=98+98) GorillaMux_Parse2Params 3.44µs ± 8% 2.82µs ± 7% -18.04% (p=0.000 n=98+94) GorillaMux_ParseAll 111µs ± 5% 91µs ±13% -18.12% (p=0.000 n=96+98) GorillaMux_StaticAll 1.13ms ± 4% 0.95ms ± 9% -16.38% (p=0.000 n=97+96) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.98kB ± 0% -29.07% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.14kB ± 0% -38.49% (p=0.000 n=100+100) GorillaMux_ParamWrite 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 173kB ± 0% -33.02% (p=0.000 n=80+100) GorillaMux_GPlusStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 11.1kB ± 0% -32.82% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 19.6kB ± 0% -37.02% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 78kB ± 0% -50.79% (p=0.000 n=100+95) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 8.0 ± 0% -33.33% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.48k ± 0% -25.78% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 96 ± 0% -25.00% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 168 ± 0% -32.80% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.63k ± 0% -55.56% (p=0.000 n=100+100) ``` --- </details> <details> <summary> Older Xeon E, 2.4 GHz </summary> Before vs After with omit Route flag enabled ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz name old time/op new time/op delta GorillaMux_Param 3.31µs ±11% 2.44µs ±11% -26.34% (p=0.000 n=95+92) GorillaMux_Param5 4.68µs ± 9% 3.96µs ±14% -15.22% (p=0.000 n=97+100) GorillaMux_Param20 11.1µs ±10% 7.2µs ± 9% -35.03% (p=0.000 n=100+97) GorillaMux_ParamWrite 3.37µs ±10% 2.56µs ± 8% -24.21% (p=0.000 n=95+94) GorillaMux_GithubStatic 6.90µs ± 7% 3.85µs ± 8% -44.16% (p=0.000 n=96+91) GorillaMux_GithubParam 9.85µs ± 6% 8.89µs ±11% -9.74% (p=0.000 n=98+96) GorillaMux_GithubAll 5.15ms ±10% 4.77ms ± 7% -7.36% (p=0.000 n=96+96) GorillaMux_GPlusStatic 2.38µs ± 8% 0.36µs ± 7% -84.98% (p=0.000 n=95+94) GorillaMux_GPlusParam 4.30µs ±11% 3.33µs ±10% -22.60% (p=0.000 n=97+95) GorillaMux_GPlus2Params 7.80µs ± 8% 6.82µs ±10% -12.55% (p=0.000 n=98+94) GorillaMux_GPlusAll 65.8µs ±10% 50.5µs ±10% -23.24% (p=0.000 n=97+98) GorillaMux_ParseStatic 2.98µs ±10% 0.70µs ± 9% -76.68% (p=0.000 n=99+94) GorillaMux_ParseParam 3.31µs ± 9% 2.55µs ± 9% -23.11% (p=0.000 n=96+95) GorillaMux_Parse2Params 3.92µs ± 8% 3.18µs ±12% -18.86% (p=0.000 n=97+96) GorillaMux_ParseAll 125µs ± 9% 90µs ±12% -28.23% (p=0.000 n=99+96) GorillaMux_StaticAll 1.32ms ± 6% 0.79ms ± 6% -40.41% (p=0.000 n=99+95) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.93kB ± 0% -32.56% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.10kB ± 0% -39.86% (p=0.000 n=100+79) GorillaMux_ParamWrite 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 149kB ± 0% -42.37% (p=0.000 n=79+86) GorillaMux_GPlusStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 9.7kB ± 0% -41.43% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 14.4kB ± 0% -53.88% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 8kB ± 0% -95.24% (p=0.000 n=100+100) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 7.0 ± 0% -41.67% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.21k ± 0% -39.57% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 79 ± 0% -38.28% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 122 ± 0% -51.20% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.16k ± 0% -88.89% (p=0.000 n=100+100) ``` Before vs After ``` goos: linux goarch: amd64 pkg: github.com/gorilla/mux cpu: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz name old time/op new time/op delta GorillaMux_Param 3.31µs ±11% 2.59µs ±12% -21.76% (p=0.000 n=95+96) GorillaMux_Param5 4.68µs ± 9% 3.80µs ± 7% -18.79% (p=0.000 n=97+92) GorillaMux_Param20 11.1µs ±10% 7.2µs ± 9% -35.19% (p=0.000 n=100+99) GorillaMux_ParamWrite 3.37µs ±10% 2.68µs ± 7% -20.69% (p=0.000 n=95+95) GorillaMux_GithubStatic 6.90µs ± 7% 5.06µs ± 7% -26.57% (p=0.000 n=96+91) GorillaMux_GithubParam 9.85µs ± 6% 8.83µs ± 9% -10.42% (p=0.000 n=98+98) GorillaMux_GithubAll 5.15ms ±10% 4.71ms ± 9% -8.50% (p=0.000 n=96+97) GorillaMux_GPlusStatic 2.38µs ± 8% 1.19µs ±10% -50.24% (p=0.000 n=95+100) GorillaMux_GPlusParam 4.30µs ±11% 3.40µs ± 5% -21.08% (p=0.000 n=97+96) GorillaMux_GPlus2Params 7.80µs ± 8% 6.96µs ± 8% -10.71% (p=0.000 n=98+98) GorillaMux_GPlusAll 65.8µs ±10% 52.2µs ±10% -20.65% (p=0.000 n=97+96) GorillaMux_ParseStatic 2.98µs ±10% 1.61µs ±10% -46.04% (p=0.000 n=99+100) GorillaMux_ParseParam 3.31µs ± 9% 2.63µs ± 7% -20.46% (p=0.000 n=96+91) GorillaMux_Parse2Params 3.92µs ± 8% 3.23µs ± 6% -17.58% (p=0.000 n=97+93) GorillaMux_ParseAll 125µs ± 9% 102µs ± 9% -18.79% (p=0.000 n=99+96) GorillaMux_StaticAll 1.32ms ± 6% 1.07ms ± 7% -18.78% (p=0.000 n=99+95) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Param5 1.38kB ± 0% 0.98kB ± 0% -29.07% (p=0.000 n=100+100) GorillaMux_Param20 3.48kB ± 0% 2.14kB ± 0% -38.49% (p=0.000 n=100+100) GorillaMux_ParamWrite 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GithubStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GithubParam 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GithubAll 258kB ± 0% 173kB ± 0% -33.02% (p=0.000 n=79+96) GorillaMux_GPlusStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_GPlusParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_GPlus2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_GPlusAll 16.5kB ± 0% 11.1kB ± 0% -32.82% (p=0.000 n=100+100) GorillaMux_ParseStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=100+100) GorillaMux_ParseParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=100+100) GorillaMux_Parse2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=100+100) GorillaMux_ParseAll 31.1kB ± 0% 19.6kB ± 0% -37.02% (p=0.000 n=100+100) GorillaMux_StaticAll 158kB ± 0% 78kB ± 0% -50.79% (p=0.000 n=100+100) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param5 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Param20 12.0 ± 0% 8.0 ± 0% -33.33% (p=0.000 n=100+100) GorillaMux_ParamWrite 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GithubParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GithubAll 1.99k ± 0% 1.48k ± 0% -25.78% (p=0.000 n=100+100) GorillaMux_GPlusStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_GPlusParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlus2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_GPlusAll 128 ± 0% 96 ± 0% -25.00% (p=0.000 n=100+100) GorillaMux_ParseStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=100+100) GorillaMux_ParseParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_Parse2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=100+100) GorillaMux_ParseAll 250 ± 0% 168 ± 0% -32.80% (p=0.000 n=100+100) GorillaMux_StaticAll 1.41k ± 0% 0.63k ± 0% -55.56% (p=0.000 n=100+100) ``` --- </details> <details> <summary> Older i7, frequency scaling around 3.4 GHz, n=10 </summary> Sorry, only 10 iterations each. I do not want to hear the fan for too long :) Before vs After with omit Route flag enabled ``` goos: linux goarch: amd64 pkg: github.com/julienschmidt/go-http-routing-benchmark cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz name old time/op new time/op delta GorillaMux_Param 1.80µs ± 2% 1.41µs ± 3% -21.64% (p=0.000 n=10+10) GorillaMux_Param5 2.68µs ± 0% 2.34µs ± 1% -12.43% (p=0.000 n=10+10) GorillaMux_Param20 5.92µs ± 0% 4.02µs ± 0% -32.10% (p=0.000 n=10+9) GorillaMux_ParamWrite 1.89µs ± 1% 1.47µs ± 0% -22.22% (p=0.000 n=9+8) GorillaMux_GithubStatic 4.05µs ± 1% 2.80µs ± 0% -31.04% (p=0.000 n=9+10) GorillaMux_GithubParam 6.30µs ± 1% 5.90µs ± 1% -6.27% (p=0.000 n=10+10) GorillaMux_GithubAll 3.14ms ± 1% 2.87ms ± 2% -8.42% (p=0.000 n=10+10) GorillaMux_GPlusStatic 1.29µs ± 1% 0.23µs ± 1% -82.37% (p=0.000 n=10+10) GorillaMux_GPlusParam 2.52µs ± 0% 2.07µs ± 1% -17.69% (p=0.000 n=10+10) GorillaMux_GPlus2Params 4.92µs ± 0% 4.49µs ± 1% -8.71% (p=0.000 n=10+10) GorillaMux_GPlusAll 39.0µs ± 1% 31.5µs ± 1% -19.28% (p=0.000 n=10+10) GorillaMux_ParseStatic 1.58µs ± 1% 0.47µs ± 1% -70.01% (p=0.000 n=10+10) GorillaMux_ParseParam 1.89µs ± 0% 1.46µs ± 1% -22.70% (p=0.000 n=10+10) GorillaMux_Parse2Params 2.31µs ± 2% 1.87µs ± 0% -18.96% (p=0.000 n=10+8) GorillaMux_ParseAll 74.3µs ± 1% 55.4µs ± 0% -25.48% (p=0.000 n=10+10) GorillaMux_StaticAll 797µs ± 0% 561µs ± 1% -29.66% (p=0.000 n=10+10) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=10+10) GorillaMux_Param5 1.38kB ± 0% 0.93kB ± 0% -32.56% (p=0.000 n=10+10) GorillaMux_Param20 3.48kB ± 0% 2.09kB ± 0% -39.87% (p=0.000 n=10+10) GorillaMux_ParamWrite 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=10+10) GorillaMux_GithubStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=10+10) GorillaMux_GithubParam 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=10+10) GorillaMux_GithubAll 258kB ± 0% 149kB ± 0% -42.37% (p=0.000 n=10+9) GorillaMux_GPlusStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=10+10) GorillaMux_GPlusParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=10+10) GorillaMux_GPlus2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=10+10) GorillaMux_GPlusAll 16.5kB ± 0% 9.7kB ± 0% -41.43% (p=0.000 n=10+10) GorillaMux_ParseStatic 1.01kB ± 0% 0.05kB ± 0% -95.24% (p=0.000 n=10+10) GorillaMux_ParseParam 1.31kB ± 0% 0.86kB ± 0% -34.15% (p=0.000 n=10+10) GorillaMux_Parse2Params 1.33kB ± 0% 0.88kB ± 0% -33.73% (p=0.000 n=10+10) GorillaMux_ParseAll 31.1kB ± 0% 14.4kB ± 0% -53.88% (p=0.000 n=10+10) GorillaMux_StaticAll 158kB ± 0% 8kB ± 0% -95.24% (p=0.000 n=10+10) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_Param5 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_Param20 12.0 ± 0% 7.0 ± 0% -41.67% (p=0.000 n=10+10) GorillaMux_ParamWrite 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_GithubStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=10+10) GorillaMux_GithubParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_GithubAll 1.99k ± 0% 1.21k ± 0% -39.57% (p=0.000 n=10+10) GorillaMux_GPlusStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=10+10) GorillaMux_GPlusParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_GPlus2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_GPlusAll 128 ± 0% 79 ± 0% -38.28% (p=0.000 n=10+10) GorillaMux_ParseStatic 9.00 ± 0% 1.00 ± 0% -88.89% (p=0.000 n=10+10) GorillaMux_ParseParam 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_Parse2Params 10.0 ± 0% 7.0 ± 0% -30.00% (p=0.000 n=10+10) GorillaMux_ParseAll 250 ± 0% 122 ± 0% -51.20% (p=0.000 n=10+10) GorillaMux_StaticAll 1.41k ± 0% 0.16k ± 0% -88.89% (p=0.000 n=10+10) ``` Before vs After ``` goos: linux goarch: amd64 pkg: github.com/julienschmidt/go-http-routing-benchmark cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz name old time/op new time/op delta GorillaMux_Param 1.80µs ± 2% 1.38µs ± 2% -23.29% (p=0.000 n=10+10) GorillaMux_Param5 2.68µs ± 0% 2.29µs ± 1% -14.51% (p=0.000 n=10+10) GorillaMux_Param20 5.92µs ± 0% 3.95µs ± 1% -33.32% (p=0.000 n=10+10) GorillaMux_ParamWrite 1.89µs ± 1% 1.46µs ± 2% -22.59% (p=0.000 n=9+10) GorillaMux_GithubStatic 4.05µs ± 1% 3.41µs ± 1% -15.89% (p=0.000 n=9+9) GorillaMux_GithubParam 6.30µs ± 1% 5.80µs ± 1% -7.91% (p=0.000 n=10+10) GorillaMux_GithubAll 3.14ms ± 1% 2.89ms ± 1% -7.79% (p=0.000 n=10+10) GorillaMux_GPlusStatic 1.29µs ± 1% 0.65µs ± 1% -49.87% (p=0.000 n=10+10) GorillaMux_GPlusParam 2.52µs ± 0% 2.14µs ± 1% -15.03% (p=0.000 n=10+10) GorillaMux_GPlus2Params 4.92µs ± 0% 4.46µs ± 1% -9.40% (p=0.000 n=10+10) GorillaMux_GPlusAll 39.0µs ± 1% 33.0µs ± 1% -15.53% (p=0.000 n=10+10) GorillaMux_ParseStatic 1.58µs ± 1% 0.93µs ± 1% -41.36% (p=0.000 n=10+10) GorillaMux_ParseParam 1.89µs ± 0% 1.51µs ± 2% -20.23% (p=0.000 n=10+9) GorillaMux_Parse2Params 2.31µs ± 2% 1.92µs ± 1% -16.95% (p=0.000 n=10+10) GorillaMux_ParseAll 74.3µs ± 1% 60.9µs ± 1% -17.99% (p=0.000 n=10+10) GorillaMux_StaticAll 797µs ± 0% 699µs ± 0% -12.25% (p=0.000 n=10+10) name old alloc/op new alloc/op delta GorillaMux_Param 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=10+10) GorillaMux_Param5 1.38kB ± 0% 0.98kB ± 0% -29.07% (p=0.000 n=10+10) GorillaMux_Param20 3.48kB ± 0% 2.14kB ± 0% -38.48% (p=0.000 n=10+10) GorillaMux_ParamWrite 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=10+10) GorillaMux_GithubStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=10+10) GorillaMux_GithubParam 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=10+10) GorillaMux_GithubAll 258kB ± 0% 173kB ± 0% -33.02% (p=0.000 n=10+10) GorillaMux_GPlusStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=10+10) GorillaMux_GPlusParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=10+10) GorillaMux_GPlus2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=10+10) GorillaMux_GPlusAll 16.5kB ± 0% 11.1kB ± 0% -32.82% (p=0.000 n=10+10) GorillaMux_ParseStatic 1.01kB ± 0% 0.50kB ± 0% -50.79% (p=0.000 n=10+10) GorillaMux_ParseParam 1.31kB ± 0% 0.91kB ± 0% -30.49% (p=0.000 n=10+10) GorillaMux_Parse2Params 1.33kB ± 0% 0.93kB ± 0% -30.12% (p=0.000 n=10+10) GorillaMux_ParseAll 31.1kB ± 0% 19.6kB ± 0% -37.02% (p=0.000 n=10+10) GorillaMux_StaticAll 158kB ± 0% 78kB ± 0% -50.79% (p=0.000 n=10+10) name old allocs/op new allocs/op delta GorillaMux_Param 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_Param5 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_Param20 12.0 ± 0% 8.0 ± 0% -33.33% (p=0.000 n=10+10) GorillaMux_ParamWrite 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_GithubStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=10+10) GorillaMux_GithubParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_GithubAll 1.99k ± 0% 1.48k ± 0% -25.78% (p=0.000 n=10+10) GorillaMux_GPlusStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=10+10) GorillaMux_GPlusParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_GPlus2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_GPlusAll 128 ± 0% 96 ± 0% -25.00% (p=0.000 n=10+10) GorillaMux_ParseStatic 9.00 ± 0% 4.00 ± 0% -55.56% (p=0.000 n=10+10) GorillaMux_ParseParam 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_Parse2Params 10.0 ± 0% 8.0 ± 0% -20.00% (p=0.000 n=10+10) GorillaMux_ParseAll 250 ± 0% 168 ± 0% -32.80% (p=0.000 n=10+10) GorillaMux_StaticAll 1.41k ± 0% 0.63k ± 0% -55.56% (p=0.000 n=10+10) ``` --- </details> --- </details> --- </details> If you read this far, please consider running benchmarks for your own use cases of `mux` and report back any changes. Thanks! <details> <summary> go.mod override </summary> You can use the following override in your `go.mod` file: ``` replace github.com/gorilla/mux v1.8.1 => github.com/das7pad/mux v1.8.1-0.20220803193445-4e593050ec93 ``` Optionally, you can enable the flag for not storing the `Route` in the request context: ``` m := mux.NewRouter() m.OmitRouteFromContext(true) ``` </details> --------- Signed-off-by: Jakob Ackermann <[email protected]> Co-authored-by: Alex Vulaj <[email protected]>
1 parent f79c3af commit e44017d

File tree

5 files changed

+303
-108
lines changed

5 files changed

+303
-108
lines changed

bench_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,38 @@ func BenchmarkMux(b *testing.B) {
2121
}
2222
}
2323

24+
func BenchmarkMuxSimple(b *testing.B) {
25+
router := new(Router)
26+
handler := func(w http.ResponseWriter, r *http.Request) {}
27+
router.HandleFunc("/status", handler)
28+
29+
testCases := []struct {
30+
name string
31+
omitRouteFromContext bool
32+
}{
33+
{
34+
name: "default",
35+
omitRouteFromContext: false,
36+
},
37+
{
38+
name: "omit route from ctx",
39+
omitRouteFromContext: true,
40+
},
41+
}
42+
for _, tc := range testCases {
43+
b.Run(tc.name, func(b *testing.B) {
44+
router.OmitRouteFromContext(tc.omitRouteFromContext)
45+
46+
request, _ := http.NewRequest("GET", "/status", nil)
47+
b.ReportAllocs()
48+
b.ResetTimer()
49+
for i := 0; i < b.N; i++ {
50+
router.ServeHTTP(nil, request)
51+
}
52+
})
53+
}
54+
}
55+
2456
func BenchmarkMuxAlternativeInRegexp(b *testing.B) {
2557
router := new(Router)
2658
handler := func(w http.ResponseWriter, r *http.Request) {}

mux.go

+45-12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"errors"
1010
"fmt"
1111
"net/http"
12+
"net/url"
1213
"path"
1314
"regexp"
1415
)
@@ -84,6 +85,9 @@ type routeConf struct {
8485
// will not redirect
8586
skipClean bool
8687

88+
// If true, the http.Request context will not contain the Route.
89+
omitRouteFromContext bool
90+
8791
// Manager for the variables from host and path.
8892
regexp routeRegexpGroup
8993

@@ -180,15 +184,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
180184
}
181185
// Clean path to canonical form and redirect.
182186
if p := cleanPath(path); p != path {
183-
184-
// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
185-
// This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
186-
// http://code.google.com/p/go/issues/detail?id=5252
187-
url := *req.URL
188-
url.Path = p
189-
p = url.String()
190-
191-
w.Header().Set("Location", p)
187+
w.Header().Set("Location", replaceURLPath(req.URL, p))
192188
w.WriteHeader(http.StatusMovedPermanently)
193189
return
194190
}
@@ -197,8 +193,15 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
197193
var handler http.Handler
198194
if r.Match(req, &match) {
199195
handler = match.Handler
200-
req = requestWithVars(req, match.Vars)
201-
req = requestWithRoute(req, match.Route)
196+
if handler != nil {
197+
// Populate context for custom handlers
198+
if r.omitRouteFromContext {
199+
// Only populate the match vars (if any) into the context.
200+
req = requestWithVars(req, match.Vars)
201+
} else {
202+
req = requestWithRouteAndVars(req, match.Route, match.Vars)
203+
}
204+
}
202205
}
203206

204207
if handler == nil && match.MatchErr == ErrMethodMismatch {
@@ -260,6 +263,16 @@ func (r *Router) SkipClean(value bool) *Router {
260263
return r
261264
}
262265

266+
// OmitRouteFromContext defines the behavior of omitting the Route from the
267+
//
268+
// http.Request context.
269+
//
270+
// CurrentRoute will yield nil with this option.
271+
func (r *Router) OmitRouteFromContext(value bool) *Router {
272+
r.omitRouteFromContext = value
273+
return r
274+
}
275+
263276
// UseEncodedPath tells the router to match the encoded original path
264277
// to the routes.
265278
// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to".
@@ -445,13 +458,25 @@ func CurrentRoute(r *http.Request) *Route {
445458
return nil
446459
}
447460

461+
// requestWithRouteAndVars adds the matched vars to the request ctx.
462+
// It shortcuts the operation when the vars are empty.
448463
func requestWithVars(r *http.Request, vars map[string]string) *http.Request {
464+
if len(vars) == 0 {
465+
return r
466+
}
449467
ctx := context.WithValue(r.Context(), varsKey, vars)
450468
return r.WithContext(ctx)
451469
}
452470

453-
func requestWithRoute(r *http.Request, route *Route) *http.Request {
471+
// requestWithRouteAndVars adds the matched route and vars to the request ctx.
472+
// It saves extra allocations in cloning the request once and skipping the
473+
//
474+
// population of empty vars, which in turn mux.Vars can handle gracefully.
475+
func requestWithRouteAndVars(r *http.Request, route *Route, vars map[string]string) *http.Request {
454476
ctx := context.WithValue(r.Context(), routeKey, route)
477+
if len(vars) > 0 {
478+
ctx = context.WithValue(ctx, varsKey, vars)
479+
}
455480
return r.WithContext(ctx)
456481
}
457482

@@ -478,6 +503,14 @@ func cleanPath(p string) string {
478503
return np
479504
}
480505

506+
// replaceURLPath prints an url.URL with a different path.
507+
func replaceURLPath(u *url.URL, p string) string {
508+
// Operate on a copy of the request url.
509+
u2 := *u
510+
u2.Path = p
511+
return u2.String()
512+
}
513+
481514
// uniqueVars returns an error if two slices contain duplicated strings.
482515
func uniqueVars(s1, s2 []string) error {
483516
for _, v1 := range s1 {

0 commit comments

Comments
 (0)