yas,一个开源的 C++ 库:比 Protobuf 快 10 倍的序列化方案
在 C++ 项目中做序列化,你通常会遇到几个选择:手写二进制、用 JSON(慢且臃肿)、用 Protobuf(要写 .proto 文件还要跑代码生成器)。YAS(Yet Another Serialization) 提供了一个折中方案:纯头文件、零依赖、性能极致。
项目简介
YAS 是一个 C++11 的 header-only 序列化库,由 niXman 开发维护(2012 年创建,至今仍在活跃更新)。它的设计目标是替代 boost.serialization,解决其序列化速度不足的问题。
- Star 数:787(GitHub)
- License:自定义许可(非标准开源协议,商用需注意)
- 支持编译器:GCC 4.8.5+、Clang 3.5+、MSVC 2017+、MinGW、Emscripten
性能表现
根据 CppCon 2022 和多个第三方 benchmark:
| 序列化库 | 100,000 次耗时 | 二进制体积 |
|---|---|---|
| YAS | 3.6 秒 | 51 KB |
| FlatBuffers | 13 秒 | - |
| MsgPack | 18 秒 | - |
| Protobuf | 38 秒 | - |
| 手写最优代码 | ~3 秒 | - |
YAS 比 Protobuf 快约 10 倍,生成的二进制比多数竞品更紧凑。
支持的归档格式
YAS 支持三种归档格式:
- 二进制(binary) — 最快最紧凑,endian 无关
- 文本(text) — 人类可读,方便调试
- JSON(json) — 不完全符合 JSON 标准,但可与 Web 端交互
代码示例
基础用法
#include <yas/serialize.hpp>
#include <yas/std_types.hpp>
int main() {
int a = 3, aa{};
short b = 4, bb{};
float c = 3.14, cc{};
constexpr std::size_t flags =
yas::mem // IO 类型(内存)
| yas::json; // IO 格式
auto buf = yas::save<flags>(
YAS_OBJECT("myobject", a, b, c)
);
// buf = {"a":3,"b":4,"c":3.14}
yas::load<flags>(buf,
YAS_OBJECT_NVP("myobject"
,("a", aa)
,("b", bb)
,("c", cc)
)
);
// a == aa && b == bb && c == cc;
}
支持的类型
YAS 内置支持大量标准库和 Boost 类型:
标准库:std::vector、std::map、std::string、std::array、std::tuple、std::optional、std::variant、std::chrono::duration 等。
Boost:boost::optional、boost::variant、boost::container::vector 等。
Qt:QString、QList、QMap、QVector、QByteArray 等。
优缺点分析
优点
- 极速:序列化速度远超 Protobuf、MsgPack、FlatBuffers
- 紧凑:生成的二进制体积最小
- 纯头文件:
#include即可使用,无需编译 - 零依赖:不依赖 Boost 或第三方库
- 跨平台:支持 GCC/Clang/MSVC/MinGW/Emscripten
- Endian 无关:二进制归档可在不同字节序机器间传输
缺点
- 无版本兼容:改了结构体定义,旧文件就无法读取(不像 Protobuf 有前向/后向兼容)
- 有模式(schema-ful):需要提前声明序列化字段,不能像 JSON 那样随意
- License 非标准:需注意商用合规性
适用场景
YAS 适合以下场景:
- 游戏存档:需要快速序列化/反序列化大量对象
- 网络协议:进程间通信、客户端-服务器数据传输
- 性能敏感场景:对序列化和体积有极致要求
不适合:需要长期演进的数据存储(没有版本兼容能力)。
与类似库对比
| 特性 | YAS | Protobuf | FlatBuffers | MsgPack |
|---|---|---|---|---|
| 零依赖 | ✅ | ❌ | ❌ | ✅ |
| 纯头文件 | ✅ | ❌ | ❌ | ✅ |
| 需代码生成 | ❌ | ✅ | ✅ | ❌ |
| 版本兼容 | ❌ | ✅ | ✅ | ❌ |
| 性能 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
总结
如果你在 C++ 项目中需要高性能二进制序列化,且不关心跨版本兼容,YAS 是一个比 Protobuf 快一个数量级、代码照样清爽的选择。
配合 reflect-cpp 使用,可以进一步简化代码(用反射自动注册字段)。
GitHub:https://github.com/niXman/yas(⭐ 787)
基准测试:https://github.com/thekvs/cpp-serializers