Performance & Benchmarks
goninja keeps a small benchmark suite to catch regressions in the request path. These are reproducible baselines for this repository, not claims that one framework is universally faster than another.
What is measured
Every benchmark seeds an in-memory SQLite database with 1,000 rows, starts a
real goninjatest HTTP server, then measures complete HTTP GET requests.
The measured work includes routing, generated handlers, GORM queries,
conversion to generated response types, JSON encoding, and response-body
draining. Seeding happens before the timer starts.
Task list
GET /tasksList query and collection serialization.
Filtered book list
GET /books?published=true&…Filter parsing, WHERE construction, count, list query, and serialization.
Book detail + preload
GET /books/{id}Detail retrieval plus the automatic belongs-to preload.
Current tracked baseline
Tracked baseline
Ten samples per benchmark · representative medians
Task list
GET /tasks75.5µs / op
- Memory
- 19.6 KB
- Allocs
- 415
Filtered book list
GET /books?…189.0µs / op
- Memory
- 37.3 KB
- Allocs
- 840
Book detail + preload
GET /books/{id}69.2µs / op
- Memory
- 22.8 KB
- Allocs
- 276
The raw file, rather than this table, is the source of truth. Hardware, Go version, database driver, operating-system load, and the benchmark workload all affect the result.
Run the suite
$ make bench
That runs each benchmark once with Go’s normal benchmark calibration. To refresh the committed ten-sample baseline deliberately:
$ make bench-baseline
Review and commit that file only when a change in the numbers is understood. It is not an automatic maintenance task.
Regression protection in CI
Pull requests that affect Go code, benchmark tooling, or their dependencies
run make bench-check. CI takes ten fresh samples, compares them with the
tracked baseline using benchstat, and fails only for a statistically
significant regression above 25% in time, bytes allocated, or allocations.
The comparison report is uploaded as a build artifact even when the check
fails.
The threshold is intentionally wide because shared CI runners are noisy. A passing check means “no large measured regression under this workload,” not “performance is proven for every application.” Profile a real workload before making an optimization decision.