Files
http/bench_compat_test.go
T
zeekay 5aa0d29f91 perf: zero-alloc ZAP-HTTP codec + pooled server/client hot path
Hand-rolled frame encoder/decoder (codec.go) replaces the zap.Builder +
map[string][]string + json.Marshal path. Wire stays byte-identical (golden
tests + TestCodec_CrossCheck vs a zap.Builder oracle across a wide corpus,
incl. special-char headers). Headers are streamed straight into the frame tail
as compact sorted-key JSON, byte-identical to json.Marshal, with a stdlib
fallback for escape/UTF-8 values; decode scans the JSON in place into the
fasthttp store with a json.Unmarshal fallback.

Server: one RequestCtx per connection (Init2 + per-request Reset) instead of a
per-request heap alloc; reused frame read/write buffers; single-syscall
length-prefixed response write.
Client: per-conn reused request/response buffers, single frame-type peek + one
decode (was double zap.Parse), single-syscall request write.

Codec allocs/op (default GOGC):
  MarshalRequest  11 -> 1 (Append: 0)   MarshalResponse 19 -> 1 (Append: 0)
  UnmarshalResponse 11 -> 0             hot Append/Unmarshal all 0 allocs/op
2026-07-17 01:20:47 -07:00

82 lines
1.9 KiB
Go

package zaphttp_test
// Exported-API-only codec benchmarks. These use only MarshalRequest /
// MarshalResponse / UnmarshalRequest / UnmarshalResponse, so the SAME file
// compiles and runs against both v0.2.0 (the pre-optimization baseline) and the
// zero-alloc branch — an apples-to-apples before/after of allocs/op.
import (
"testing"
"github.com/valyala/fasthttp"
zaphttp "github.com/zap-proto/http"
)
func compatReq() *fasthttp.Request {
req := fasthttp.AcquireRequest()
req.Header.SetMethod("GET")
req.SetRequestURI("/health")
req.Header.SetHost("192.168.77.2:8391")
return req
}
func compatResp() *fasthttp.Response {
resp := fasthttp.AcquireResponse()
resp.SetStatusCode(200)
resp.Header.SetContentType("text/plain; charset=utf-8")
resp.SetBodyString("ok")
return resp
}
func BenchmarkCompat_MarshalRequest(b *testing.B) {
req := compatReq()
defer fasthttp.ReleaseRequest(req)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := zaphttp.MarshalRequest(req); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCompat_MarshalResponse(b *testing.B) {
resp := compatResp()
defer fasthttp.ReleaseResponse(resp)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := zaphttp.MarshalResponse(resp); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCompat_UnmarshalRequest(b *testing.B) {
req := compatReq()
frame, _ := zaphttp.MarshalRequest(req)
fasthttp.ReleaseRequest(req)
var dst fasthttp.Request
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := zaphttp.UnmarshalRequest(frame, &dst); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCompat_UnmarshalResponse(b *testing.B) {
resp := compatResp()
frame, _ := zaphttp.MarshalResponse(resp)
fasthttp.ReleaseResponse(resp)
var dst fasthttp.Response
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := zaphttp.UnmarshalResponse(frame, &dst); err != nil {
b.Fatal(err)
}
}
}