Benchmarks
These numbers measure the router alone: handlers and middleware do nothing, so what’s left is the cost of matching, params and dispatch. Your handlers will dominate a real request; the point is that the router adds as little as possible.
v5 against v4
Section titled “v5 against v4”Both versions ran on the same harness, with the same routes and requests.
Show as a table
| Scenario | v4 | v5 |
|---|---|---|
| Static route | 20.0 ns0 allocs | 19.9 ns0 allocs |
| Static, 5 segments | 28.5 ns0 allocs | 30.2 ns0 allocs |
| One param | 87.0 ns4 allocs | 93.6 ns2 allocs |
| Three params + regexp | 150.1 ns4 allocs | 148.5 ns2 allocs |
| Static + 3 middleware | 170.4 ns6 allocs | 23.8 ns0 allocs |
| One param + 3 middleware | 238.4 ns10 allocs | 100.8 ns2 allocs |
| 404 Not Found | 20.0 ns0 allocs | 20.3 ns0 allocs |
| 405 Method Not Allowed | 60.8 ns3 allocs | 55.8 ns2 allocs |
Apple M4 Max, Go 1.27.0, median of 5 runs.
Show as a table
| Scenario | v4 | v5 |
|---|---|---|
| Static route | 30.0 ns1 alloc | 16.9 ns0 allocs |
| Static, 5 segments | 39.0 ns1 alloc | 26.2 ns0 allocs |
| One param | 50.1 ns3 allocs | 38.5 ns0 allocs |
| Three params + regexp | 110.2 ns3 allocs | 87.4 ns0 allocs |
| Static + 3 middleware | 173.1 ns7 allocs | 18.3 ns0 allocs |
| One param + 3 middleware | 192.8 ns9 allocs | 39.5 ns0 allocs |
| 404 Not Found | 29.7 ns1 alloc | 15.3 ns0 allocs |
| 405 Method Not Allowed | 89.0 ns3 allocs | 69.5 ns1 alloc |
Apple M4 Max, Go 1.27.0, median of 5 runs.
The biggest gains are behind middleware: v4 composed each route’s middleware chain on every request, v5 composes it once at registration. On fasthttp, v5 also stopped allocating for params, 404s and literal routes.
v5’s own suite
Section titled “v5’s own suite”Each row routes one request, except API, which averages a request across a realistic 70-route REST API.
| Benchmark | Time | Memory | Allocations |
|---|---|---|---|
Static/1One literal segment | 15.0 ns | 0 B | 0 |
Static/5Five literal segments | 31.6 ns | 0 B | 0 |
Static/20Twenty literal segments | 98.8 ns | 0 B | 0 |
Param/1One param | 90.3 ns | 336 B | 2 |
Param/5Five params | 132.2 ns | 336 B | 2 |
Param/20Twenty params | 883.4 ns | 2137 B | 7 |
Regexp/1One regexp param | 157.6 ns | 336 B | 2 |
Regexp/5Five regexp params | 434.8 ns | 336 B | 2 |
MiddlewareLiteral route behind 3 middleware | 23.1 ns | 0 B | 0 |
NotFound404 | 18.9 ns | 0 B | 0 |
MethodNotAllowed405 with an Allow header | 55.7 ns | 32 B | 2 |
MountRequest through a mounted router | 83.0 ns | 448 B | 1 |
APIAverage over a 70-route API | 95.5 ns | 226 B | 1.3 |
| Benchmark | Time | Memory | Allocations |
|---|---|---|---|
Static/1One literal segment | 11.6 ns | 0 B | 0 |
Static/5Five literal segments | 27.1 ns | 0 B | 0 |
Static/20Twenty literal segments | 93.3 ns | 0 B | 0 |
Param/1One param | 33.0 ns | 0 B | 0 |
Param/5Five params | 66.6 ns | 0 B | 0 |
Param/20Twenty params | 250.0 ns | 0 B | 0 |
Regexp/1One regexp param | 89.7 ns | 0 B | 0 |
Regexp/5Five regexp params | 353.1 ns | 0 B | 0 |
MiddlewareLiteral route behind 3 middleware | 17.1 ns | 0 B | 0 |
NotFound404 | 14.3 ns | 0 B | 0 |
MethodNotAllowed405 with an Allow header | 65.9 ns | 16 B | 1 |
MountRequest through a mounted router, URI parsing included | 130.2 ns | 0 B | 0 |
APIAverage over a 70-route API | 53.1 ns | 0 B | 0 |
Up to eight param values fit in a buffer on the stack; a router with a longer route takes a pooled buffer instead, so it still allocates nothing.
Run them yourself
Section titled “Run them yourself”From a clone of the repository:
go test -run '^$' -bench . -benchmem ./...To compare two versions, run each a few times and compare with benchstat:
go test -run '^$' -bench . -count 10 ./... > new.txtbenchstat old.txt new.txtThe allocation counts are also enforced by tests: TestAllocations in each router package fails if a request allocates more than it should.