静态分配与恒定工作量:TigerBeetle 的两条内存安全与性能纪律
来源: matklad.github.io — 2026-09-02
概述
这是 matklad(TigerBeetle 工程师)回复一封关于'内存安全最难问题'邮件的技术随笔。作者去年写限价撮合引擎时发布过一个 use-after-free:被取消的订单在仍挂在其价格档链表里就被归还到内存池,下次分配把同一块内存给新订单,陈旧链接仍能解析。初看像是'生命周期没管好',但本质上这是带标签的联合体(tagged union)里标签没被类型系统追踪的情形。他给出两条来自 TigerStyle/TigerBeetle 的规避套路。第一条是静态分配:'初始化之后不再动态分配内存',启动时用 --orders-max=1000000 指定上限并一次性分配,运行时超限就拒绝——满负荷下无严格上限的系统会灾难性失败(OOM killer 可能杀掉整个撮合引擎)。第二条是恒定工作量:与其维护活跃订单集合,不如引入一个中性 no-op 的保留订单(reserved),订单数量守恒地在系统里流动,总是遍历全量并对保留位做空操作。这样不再需要单独追踪'活跃订单',且全量遍历更利于编译器向量化与 CPU 预取,P100 延迟随负载保持平直。作者坦承这些是装备库里的技巧,并非放之四海皆准。
核心要点
作者曾在一个撮合引擎里发布过 use-after-free:被取消订单的内存归还池后被新订单复用,陈旧链接继续解析
该 bug 实为'带标签联合体的标签未被类型系统追踪',而非单纯生命周期疏忽
静态分配纪律:初始化后不再动态分配,启动时以 --orders-max 定上限,超限即拒——避免无界增长触发 OOM
恒定工作量:用中性 reserved 订单让订单量守恒流动,总是遍历全量并对保留位做 no-op,不再单列活跃订单集合
全量遍历比按索引访问活跃订单更利于向量化与预取,P100 延迟随负载保持平直而非在峰值骤升
作者明言这是技巧而非银弹,但能显著提升在极端负载下的确定性
金句
Static allocation gives you peace of mind. The system might fail to start if you don't have enough memory, but, if it did start, you can be rest assured that it would handle overload gracefully.(静态分配给你心安:内存不足时系统也许起不来,但一旦启动,就能保证优雅地扛住过载。)
👍 0
点赞
👎 0
沉底
返回 Lobsters 首页