这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
针对网络库的优化
需求
Go net 是 BIO 模型
- 存下全部Header
- 减少系统调用次数
- 能够复用内存
- 能够多次读
优化
go net with bufio
绑定一块缓冲区,大部分的包都在4kb以下的
需求
netpoll
- 存下全部 Header
- 拷贝出完整的Body
优化
netpoll with nocopy peek
- 分配足够大的buffer
- 限制最大buffer size
不同网络库的优势
go net
- 流式友好:用户没有调用,数据一直保留在缓冲区中
- 小包性能高:连接上绑定内存,通常情况下,4kb足够,不过一旦超过4kb,buffer申请回收就导致性能低下
netpoll
- 中大包性能高:由底层进行内存管理
- 时延低
针对协议的优化
Header 解析
找到 Header Line 边界: \r\n
先找到 \n 再看它前一个是不是 \r ,这样复杂度就变成 O(N)了
SIMD : 单指令多数据流技术,golang自动使用SIMD加速技术进行匹配
针对协议相关的Headers快速解析:
- 通过 Header Key 首字母快速筛除掉完全不可能的 key
- 解析对应 value 到独立字段
- 使用 byte slice 管理对应 header 存储,方便复用
请求体中同样处理的key:
User-Agent、Content-Type、Content-Length、Connection、Transfer-Encoding
取:
- 核心字段快速解析:
- 使用byte slice 存储:更方便做内存管理,可以对内存进行复用
- 额外存储到成员变量中:采用.方式拿出成员变量
舍:
- 普通header性能较低
- 没有map结构
Header Key 规范化
aaa-bbb --> Aaa-Bbb
取:
- 超高的转换效率
- 比 net.http提高40 倍
舍:
- 额外的内存开销
- 变更困难
热点资源池化
取:
- 减少内存分配次数
- 提高了内存复用
- 降低了GC压力
- 性能提升
舍:
- 额外的 Reset 逻辑
- 请求内有效
- 问题定位难度增加
总结
- 针对网络库的优化:buffer设计
- 针对协议的优化:header 解析、热点资源池化