fasthttp的“零内存分配”指极致复用预分配对象而非真零分配;其通过sync.pool复用requestctx、池化字节切片和固定缓冲区,避免net/http频繁new对象。

FastHTTP 为什么宣称“零内存分配”
它不真的零分配,而是把绝大多数请求生命周期内的内存复用做到极致。标准 net/http 每次请求都会 new 一堆 http.Request、http.ResponseWriter、Header map、url.URL 等;FastHTTP 把这些全换成预分配的 fasthttp.RequestCtx + 池化字节切片 + 固定大小缓冲区。
实操建议:
- 所有读写都走
ctx.Request.Body()和ctx.Response.SetBodyString(),别自己make([]byte, ...) - 避免调用
ctx.PostArgs().Peek("key")后直接转string()——这会触发一次底层数组拷贝;改用ctx.FormValue("key"),它返回的是池内可复用的string(底层是 unsafe.String) - 自定义中间件里别保存
ctx到 goroutine 外部,它的字段在下一次复用时会被重置
RequestCtx 生命周期和复用陷阱
fasthttp.RequestCtx 不是每次请求新建的,而是从 sync.Pool 里取的。用完后框架自动归还——但前提是没泄露引用。
常见错误现象:
立即学习“go语言免费学习笔记(深入)”;
- 在 handler 里启动 goroutine 并传入
ctx,结果读到空 Header 或 panic:因为主协程已归还 ctx,子协程还在用 - 把
ctx.UserValue("key")存的指针指向了局部变量,下次复用时该内存已被覆盖 - 调用
ctx.TimeoutError()后继续读写,可能触发 panic:ctx 已进入清理状态
正确做法:
- 需要异步处理时,只提取必要数据(如
ctx.Method()、ctx.Path()的拷贝),别传整个ctx - 用
ctx.UserValue存值前确认类型安全,且值本身不持有对 ctx 内部字段的引用 - 超时后立即 return,别再调用
ctx.Response.*()
如何真正压测出“零分配”效果
很多人跑 go tool pprof 看到 allocs/sec 还是几百/千,就以为 FastHTTP 没生效——其实是因为测试方式不对。
使用场景:
- 用
ab或hey压测时,默认 keep-alive 关闭,每个请求都触发新连接+新 ctx 分配,掩盖了复用收益 - 代码里用了
fmt.Sprintf、log.Printf、json.Marshal,这些都会分配,和 FastHTTP 无关 - 启用了
RequestCtx.SetUserValue存 struct 而不是指针,导致每次赋值都拷贝
实操建议:
- 压测命令加
-k(keep-alive),比如:hey -z 10s -q 50 -c 100 -k http://localhost:8080/ - 用
go run -gcflags="-m -l" main.go看关键 handler 是否逃逸,确认核心路径无堆分配 - 响应体尽量用
ctx.Response.SetBodyRaw()直接传[]byte,避免SetBodyString内部的 string→[]byte 转换
和 net/http 兼容层的代价在哪
FastHTTP 提供 fasthttpadaptor 包把 http.Handler 转成 fasthttp.RequestHandler,但这层适配器会立刻破坏“零分配”承诺。
性能影响:
- 每次请求都要 new
http.Request和http.ResponseWriter,绕过所有池化逻辑 - Header、URL、Form 解析全部重新做一遍,相当于在 FastHTTP 上套了一层 net/http 的开销
- 无法使用
ctx.Timeout()、ctx.Retry等原生能力
如果你必须复用现有 http.Handler:
- 只在迁移过渡期用,别长期依赖
fasthttpadaptor.NewFastHTTPHandler - 检查是否真需要完整 http.Handler 接口——很多场景只需替换路由和中间件,而非整个 handler 树
- 注意
http.Request.Context()返回的是空 context,不是ctx,别指望它能拿到 FastHTTP 的超时或值
真正难的不是写零分配代码,是让整个调用链路——包括你引入的第三方库、日志、指标、序列化——都不偷偷 new 对象。一个 logrus.WithField 就可能让每秒多分配几万次。










