Files
fiber/middleware/static/static_bench_test.go
d94425b64f bench: router match/registration suite + BENCHMARKS.md (#3)
Prove the specificity-routing fork's performance on a representative
~70-route Hanzo cloud table (static, param, multi-param, wildcard).

- router_bench_test.go: match hot-path (app.next, 0-alloc), full dispatch,
  registration scaling (N=10/70/500/1000), and a Go 1.22 net/http.ServeMux
  routing + registration baseline, with precedence-correctness gates
  (static/param beat wildcard; fork agrees with ServeMux on every request).
- bench/: separate module (own go.mod, replace ../) that isolates the upstream
  gofiber/fiber v3.2.0 dependency — fork vs upstream match (per-route +
  aggregate sweep) and registration. Never pollutes the fork's own module.
- middleware/static: embed.FS serve benchmark (small 1 KiB + medium 64 KiB).
- BENCHMARKS.md: methodology (M1 Max, go1.26.4, -benchtime=1s -count=6,
  benchstat medians) and the real numbers.

Findings: the fork adds ZERO aggregate match cost (sweep 10.77us vs upstream
10.96us; per-route latency is a scan-order permutation, not a regression);
fiber routing is 0-alloc vs ServeMux's 1-5 allocs per dynamic route;
registration is O(n^2) (9.5ms at N=1000/method, <110us at N<=70) — the one
honest regression, and fixable with an index-based conflict check.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-11 05:06:59 -07:00

73 lines
2.0 KiB
Go

// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
// 🤖 GitHub Repository: https://github.com/gofiber/fiber
// 📌 API Documentation: https://docs.gofiber.io
package static
// Static-serving benchmarks for the embed.FS path: the ZAP web stack ships
// assets straight out of a compiled-in embed.FS (no disk touch), so this
// measures the middleware's per-request cost (path sanitize → open → detect
// content-type → stream) plus the fixed + per-byte serve cost for a small
// (1 KiB) and a medium (64 KiB) file.
//
// Served through app.Handler() on a reused *fasthttp.RequestCtx — the same
// low-overhead idiom as the router benchmarks — so the numbers are the serve
// path, not net/http↔fasthttp conversion.
//
// Run:
//
// go test -run='^$' -bench='Benchmark_Static_Serve' -benchmem -count=6 ./middleware/static
//
// Numbers and methodology: BENCHMARKS.md (fiber).
import (
"embed"
"testing"
"github.com/valyala/fasthttp"
"github.com/zap-proto/fiber/v3"
)
//go:embed testdata/small.txt testdata/medium.txt
var benchFS embed.FS
var staticServeFiles = []struct {
name string
path string
size int
}{
{"small_1KiB", "/testdata/small.txt", 1024},
{"medium_64KiB", "/testdata/medium.txt", 65536},
}
// Benchmark_Static_Serve serves a small and a medium file from embed.FS.
func Benchmark_Static_Serve(b *testing.B) {
app := fiber.New()
app.Get("/*", New("", Config{FS: benchFS}))
h := app.Handler()
for _, f := range staticServeFiles {
b.Run(f.name, func(b *testing.B) {
fctx := &fasthttp.RequestCtx{}
fctx.Request.Header.SetMethod(fiber.MethodGet)
fctx.URI().SetPath(f.path)
// Correctness gate: 200 with the full file body.
h(fctx)
if sc := fctx.Response.StatusCode(); sc != fiber.StatusOK {
b.Fatalf("%s: status %d, want 200", f.path, sc)
}
if got := len(fctx.Response.Body()); got != f.size {
b.Fatalf("%s: served %d bytes, want %d", f.path, got, f.size)
}
b.SetBytes(int64(f.size))
b.ReportAllocs()
for b.Loop() {
h(fctx)
}
})
}
}