Static Allocation, Constant Work 这篇文章探讨了内存安全(Memory Safety)、对象池(Object Pools)的底层行为,并结合 TigerBeetle 的开发理念(TigerStyle),提出了避免内存和性能缺陷的工程实践技巧。
以下是文章的主要内容总结:
1. 内存重用与类型安全
- 传统
malloc/free 的隐患:如果程序在使用完内存后发生“悬空指针”(Use-After-Free),不同的对象可能会共享同一块内存,导致严重的物理类型混淆(例如把整数当作函数指针),进而引发任意代码执行漏洞。
- 对象池(Object Pools)的改进:如果使用对象池来管理同类型的对象,逻辑上的 Use-After-Free 依然可能发生,但物理类型混淆通常会消失(因为内存被同类型的对象复用)。这会把灾难性的漏洞转化为确定性的行为。
- 类型隔离分配器(Type-Segregated Pools):通过为每种类型单独设置分配池,可以有效防止跨类型的内存混淆,虽然会牺牲一点点内存效率,但能大幅提升安全性和内存局部性。
2. 避免 Bug 的两大 TigerStyle 技巧
为了从根本上避免内存和性能问题,文章推荐了以下两种实用设计模式:
-
静态分配(Static Allocation):
- 核心思想:系统在初始化时(如启动参数中)指定并分配最大资源量(例如最多 100 万个订单),此后不再进行动态内存分配。
- 优势:避免了内存耗尽时内核随机杀死进程的灾难(OOM Killer)。系统虽然可能在启动时因内存不足而失败,但一旦启动成功,就能在过载时优雅地拒绝多余请求,保证核心服务稳定运行。
-
恒定工作量(Constant Work):
- 核心思想:摒弃传统“创建/销毁对象”的动态跟踪思维,转而采用“固定对象池 + 空操作(No-op)占位符”的模式。例如,所有未激活的订单都设为一个统一的
reserved(保留/空)状态。
- 优势:
- 认知简化:订单在系统中按守恒定律循环,状态转换更明确,便于穷举和断言检查。
- 性能稳定与可预测:系统无需单独维护活跃对象链表,而是直接遍历全量数据。这极大地便利了 CPU 缓存预取和编译器的向量化优化,使得系统在满负载下的延迟(P100 latency)保持平稳,避免了高负载下的“灰度失效”(性能突然崩塌)。
加入我们
Zig 中文社区是一个开放的组织,我们致力于推广 Zig 在中文群体中的使用,有多种方式可以参与进来:
- 供稿,分享自己使用 Zig 的心得
- 改进 ZigCC 组织下的开源项目
- 加入微信群、QQ 群、QQ 频道、Telegram 群组、Google Groups 与更多 Zig 爱好者交流
Static Allocation, Constant Work 这篇文章探讨了内存安全(Memory Safety)、对象池(Object Pools)的底层行为,并结合 TigerBeetle 的开发理念(TigerStyle),提出了避免内存和性能缺陷的工程实践技巧。
以下是文章的主要内容总结:
1. 内存重用与类型安全
malloc/free的隐患:如果程序在使用完内存后发生“悬空指针”(Use-After-Free),不同的对象可能会共享同一块内存,导致严重的物理类型混淆(例如把整数当作函数指针),进而引发任意代码执行漏洞。2. 避免 Bug 的两大 TigerStyle 技巧
为了从根本上避免内存和性能问题,文章推荐了以下两种实用设计模式:
静态分配(Static Allocation):
恒定工作量(Constant Work):
reserved(保留/空)状态。加入我们
Zig 中文社区是一个开放的组织,我们致力于推广 Zig 在中文群体中的使用,有多种方式可以参与进来: