
实测结果,非营销宣传。所有基准测试在 Linux 上运行,GCC 13.3,100,000 次迭代,CPU 固定。
核心 FIX 操作的正面对比。
| 指标 | QuickFIX | NexusFIX | 提升 |
|---|---|---|---|
| ExecutionReport 解析 | 730 ns | 246 ns | 快 3.0 倍 |
| NewOrderSingle 解析 | 661 ns | 229 ns | 快 2.9 倍 |
| 字段访问(4 个字段) | 31 ns | 11 ns | 快 2.9 倍 |
| 吞吐量 | 1.19M 消息/秒 | 4.17M 消息/秒 | 高 3.5 倍 |
| P99 延迟 | 784 ns | 258 ns | 低 3.0 倍 |
我们如何通过四个复合阶段从 730ns 优化到 246ns。
用 std::span<const char> 视图替代 std::string 拷贝,直接引用原始缓冲区。std::span 在栈上仅 16 字节——无堆分配、无拷贝、无析构。
用预索引数组替代 std::map<int, std::string>。字段访问变为一条 mov 指令,按 FIX 标签号索引。
AVX2 向量化 SOH 分隔符扫描,每周期处理 32 字节。比逐字节扫描快约 13 倍。
consteval 字段偏移表和 22 个编译期查找表消除了约 300 个运行时分支用于枚举/类型转换。
在热路径上处理 NewOrderSingle 消息。
| 操作 | QuickFIX | NexusFIX |
|---|---|---|
| 堆分配 | 约 12 次(std::string、std::map 节点) | 0 |
| 字段存储 | std::map<int, std::string> 拷贝 | std::span 视图引用原始缓冲区 |
| 解析逻辑 | 运行时 map 插入 | 编译期偏移表 |
| 内存占用 | 动态,不可预测 | 静态,预分配 PMR 池 |
| 析构开销 | 约 12 个 std::string 析构 | 0(无拥有内存) |
复合产生 3 倍性能的设计决策。
| 技术 | QuickFIX | NexusFIX |
|---|---|---|
| 内存 | 每消息堆分配 | 零拷贝 std::span 视图 |
| 字段查找 | O(log n) std::map | O(1) 直接数组索引 |
| 解析 | 逐字节扫描 | AVX2 SIMD 向量化 |
| 字段偏移 | 运行时计算 | consteval 编译期 |
| 枚举转换 | 运行时 switch(约 300 个分支) | 22 个编译期查找表 |
| 错误处理 | 异常 | std::expected(无 throw) |
研究了 11 个行业领先的库。我们学到了什么,构建了什么,测量了什么。
| 库 | 学到了什么 | 构建了什么 | 结果 |
|---|---|---|---|
| hffix | O(n) 迭代器查找对密集 FIX 数据包不够优化 | consteval 字段偏移 + O(1) 直接索引 | 14ns 字段访问 |
| Abseil | 使用 SIMD 探测和 H2 指纹的 Swiss Tables | absl::flat_hash_map 用于会话存储 | 查找速度提升 31% |
| Quill | 无锁 SPSC 队列与延迟格式化 | Quill 作为日志后端 | 8ns 中位数日志延迟 |
| NanoLog | 二进制编码 + 后台线程实现 7ns 日志 | DeferredProcessor<T> 静态二进制序列化 | 减少 84%(75→12ns) |
| liburing | DEFER_TASKRUN 消除内核任务唤醒 | io_uring + 注册缓冲区 + 多次接收 | I/O 快 7-27% |
| Highway | 跨指令集的可移植 SIMD 抽象 | 保留手动调优的 FIX 模式内联函数 | 吞吐量提升 13 倍 |
| Seastar | 无共享反应器用于高并发 I/O | CPU 核心绑定 + 无锁流水线 | P99 改善 8% |
| Folly | 高级内存栅栏和无锁原语 | 原生 SPSC 队列 + 位掩码验证 | 零外部依赖 |
| Rigtorp | 缓存行填充消除伪共享 | 使用相同技术的原生 SPSCQueue | 88M ops/sec,11ns |
| xsimd | 通用 SIMD 包装器用于数学运算 | 直接 Intel 内联函数用于 SOH 扫描 | 比包装器快 2 倍 |
| Boost.PMR | 单调缓冲区实现每消息 Arena 分配 | std::pmr::monotonic_buffer_resource | 零堆分配 |