Benchmarks comparing how quickly several Go HTTP frameworks decode input, validate it, and return a JSON response. Frameworks under test:
go test -run=^$ -bench=. -benchmem(-run=^$ skips the unit tests so only the benchmarks run.) Benchmarks are
grouped as sub-benchmarks under a few umbrella functions:
BenchmarkHandler— each framework dispatches a request in-process, with no real net/http server (ServeHTTPagainst anhttptestrecorder).BenchmarkServer— each framework is exposed on a real TCP listener and driven by a real net/http client, so every framework pays the same connection, request-write and response-read costs.BenchmarkBaseline— reference comparison of reflect and validation usage.
Example output:
BenchmarkHandler/Mid-10 277681 3965 ns/op 3678 B/op 38 allocs/op
BenchmarkHandler/Echo-10 289746 3972 ns/op 2828 B/op 38 allocs/op
BenchmarkHandler/Gin-10 277474 4119 ns/op 3637 B/op 41 allocs/op
BenchmarkHandler/Gongular-10 122493 9640 ns/op 6657 B/op 75 allocs/op
BenchmarkHandler/Fiber-10 91224 12916 ns/op 10500 B/op 65 allocs/op
BenchmarkServer/Fiber-10 20620 49169 ns/op 6924 B/op 80 allocs/op
BenchmarkServer/Gin-10 22329 52007 ns/op 10760 B/op 108 allocs/op
BenchmarkServer/Mid-10 22725 51869 ns/op 10713 B/op 105 allocs/op
BenchmarkServer/Echo-10 22814 52038 ns/op 9982 B/op 105 allocs/op
BenchmarkServer/Gongular-10 19878 59526 ns/op 14443 B/op 142 allocs/op
BenchmarkServer/Mid-fasthttp-10 17306 60861 ns/op 11919 B/op 106 allocs/op
BenchmarkBaseline/Reflection-10 3644918 326.6 ns/op 80 B/op 5 allocs/op
BenchmarkBaseline/Validator-10 962973 1233 ns/op 180 B/op 10 allocs/op
How much overhead does each framework add without a full TCP request?
A full example of making HTTP requests to a local server running each framework
Fiber is built on fasthttp rather than
net/http, so it has no in-memory ServeHTTP(recorder, req) path. In
BenchmarkHandler its bar uses app.Test(), which still routes the request
through a fasthttp server goroutine over a pipe — so it carries round-trip
overhead the others do not and should be read as indicative only.
BenchmarkServer is the fair, apples-to-apples comparison across all four
frameworks.
cmd/benchchart reads that output on stdin and writes one pair of SVG bar
charts — time (ns/op) and memory (B/op) — per benchmark group, using
go-chart:
go test -run=^$ -bench=. -benchmem | go run ./cmd/benchchartBenchmarks are grouped by the segment before the / in their name, so the
command above writes handler-ns.svg, handler-bytes.svg, server-ns.svg,
server-bytes.svg, baseline-ns.svg and baseline-bytes.svg. Adding a new
chart needs no changes to benchchart: write a new BenchmarkXxx umbrella
whose b.Run cases are the bars, and a xxx-ns.svg / xxx-bytes.svg pair is
produced automatically. A benchmark with no / in its name falls into a
default group (-default, default bench).