Yandex 开源 YaFF:零拷贝 Protobuf 线格式,读取速度接近 C++ 原生结构体
Yandex 开源了 YaFF,一种零拷贝的 Protobuf 线格式,读取速度比 FlatBuffers 快 3.8 倍,接近 C++ 原生结构体。支持四种布局,已在广告推荐系统节省 10-20% CPU。本文解读其技术细节及对中文开发者的意义。
一句话看懂
Yandex 开源了 YaFF,一种零拷贝的 Protobuf 线格式,读取速度比 FlatBuffers 快 3.8 倍,接近 C++ 原生结构体,已在生产环境节省 10-20% CPU。
详细发生了什么
Yandex 开源了 YaFF(Yet another Flat Format),一种针对 Protobuf 生态的零拷贝线格式,采用 Apache 2.0 协议,当前版本 v0.1.0,仅支持 C++。核心思路是:保留 .proto 文件作为单一数据源,只改变数据在内存中的物理布局,从而实现无需解析的直接读取。
YaFF 提供了四种布局:Fixed(固定结构,无头,零开销)、Flat(2 字节头,支持 schema 演进)、Sparse(通过元表寻址,适合稀疏 schema)和 Dynamic(默认,运行时自动选择 Flat 或 Sparse)。在 Yandex 的基准测试中,Flat 布局读取热数据仅需 9.79 ns,比 FlatBuffers(37.30 ns)快约 3.8 倍,比原生 Protobuf(219.35 ns)快约 22 倍,且仅比原始 C++ 结构体(8.14 ns)慢 1.2 倍。
YaFF 已在 Yandex 的广告推荐系统中运行,报告显示在生产规模下 CPU 节省了 10-20%。设计允许逐步采用:可以在一个热点路径中引入 YaFF,其余部分继续使用 Protobuf,通过双向转换接口无缝衔接。
中文圈视角
对于中文开发者,YaFF 的吸引力在于它解决了 Protobuf 在高负载后端中的性能瓶颈,而无需像 FlatBuffers 那样维护独立的 schema 和转换层。国内很多互联网公司(如字节跳动、腾讯、阿里)在推荐系统、广告引擎、搜索索引等场景中大量使用 Protobuf,CPU 开销往往是优化重点。YaFF 的零拷贝特性可以直接降低这些场景的延迟和资源消耗。
不过,目前 YaFF 仅支持 C++,且处于早期版本(v0.1.0),对 Java、Go、Python 等语言的支持尚未提及。国内团队如果考虑采用,需要评估技术栈匹配度。另外,YaFF 的 schema 演进规则与 Protobuf 略有不同(例如 Flat 布局要求类型保持),迁移时需注意兼容性。
与国内类似项目相比,例如腾讯的 Tars 序列化或自研的二进制协议,YaFF 的优势在于与 Protobuf 生态的无缝集成——.proto 文件无需改动,仅需额外生成 YaFF 代码。对于已经深度绑定 Protobuf 的团队,这是一个低风险的性能优化选项。
几条值得记住的细节
- 读取性能:Flat 布局读取热数据比 FlatBuffers 快 3.8 倍,比 Protobuf 快 22 倍,仅比 C++ 原生结构体慢 1.2 倍。
- 四种布局:Fixed(零开销,schema 冻结)、Flat(2 字节头,受限演进)、Sparse(6 字节头,自由演进)、Dynamic(默认,自动选择)。
- 生产验证:已在 Yandex 广告推荐系统运行,CPU 节省 10-20%。
- 逐步采用:支持与 Protobuf 双向转换,可在单个热点路径中引入,无需全量迁移。
- 开源协议:Apache 2.0,代码已托管在 GitHub,文档见 yaff.tech。
一句话总结
如果你的服务用 Protobuf 且 CPU 瓶颈在序列化,YaFF 提供了一条低成本的零拷贝优化路径,值得关注。