mirror of
https://github.com/zap-proto/http.git
synced 2026-10-04 03:07:19 +00:00
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
82 lines
1.9 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|