你的二进制协议可能正在浪费2-5倍性能,而问题不在算法——在64字节的内存块。

被忽略的硬件真相

现代CPU从不逐字节读取内存。它们以缓存行为单位批量读取——x86_64和ARM上通常是64字节。每次L1未命中,整行数据被拉入;每次跨核可见的写入,其他核心的对应缓存行被强制失效。

如果你的协议"热字段"——接收方最频繁读取的数据——恰好跨坐在两个缓存行边界上,内存流量凭空翻倍。

一个具体代价

假设一个朴素的市场数据tick结构:1字节类型标签、8字节时间戳、4字节symbol ID、8字节价格、8字节序列号、1字节标志位。编译器按对齐规则填充后约32-40字节,看似合理。

但1024个这样的消息组成队列时,只要有一个tick跨缓存行,读取它就需两次内存访问。乘以1024。

零成本修复

```cpp struct alignas(64) MarketTick { uint64_t seq; // 8B 最常被读取,放首位 uint64_t ts; // 8B uint64_t price; // 8B uint32_t sym; // 4B uint8_t type; // 1B uint8_t flags; // 1B // 显式填充至64字节边界 uint8_t pad[64 - 30]; }; ```

关键不是让单个消息更小,而是确保热数据不跨行。对齐到64字节后,每个tick独占一行,读取成本从2次降为1次。

两条铁律

1. 协议格式不仅是网络字节流,更是接收方L1缓存中的字节布局
2. 性能回报最高的工作不是算法优化,而是对硬件机制的"机械同理心"

完整基准测试和从schema自动生成缓存行正确消息的C++模板技巧,见原文深度解析。