利用 Box 节省内存预计阅读时间 5 分钟发布时间为 2026 年 4 月 23 日。通过改变一些结构体的布局以及反序列化 JSON 文件的方式为一个实际的 Rust 程序节省了 475 MB 内存该程序原本占用 895 MB 内存。目录引言实际用例关于 Rust 结构体与内存回收内存的改动验证证明影响总结简要回顾要点。实际用例程序将 中的所有 JSON 文件反序列化为 “Smithy Shape” 结构体。这些文件包含数千个类似示例的结构。程序使用了 [serde](https://docs.rs/serde/latest/serde/)。为清晰展示部分结构体这是一堆包含结构体的结构体有些是可选的并且带有 serde 属性。按照这种方式反序列化这些结构体在内存中占用了 895 MB。分析表明大多数可选字符串缺失可利用这一点减少内存占用但需了解一些 Rust 的特性。关于 Rust 结构体与内存在 64 位平台上一个字由 8 字节组成存储一个 usize 需要这么多内存。一个 String 需要 3 个字本身需要 24 字节不包括堆上实际的字符串内容。编译器有特殊优化Option 的大小和 String 相同。当 SmithyServiceTrait 结构体中的所有字符串都缺失时它在内存中正好占用 120 字节。接着看结构体组合如 Container1 结构体其最小大小是 24 120 144 字节。若把 Container 结构体改成使用 Option当 some_string 和 trait 都为 None 时容器大小和 Container1 一样使用 Option 未节省内存。将这一点应用到 SmithyTraits 上可知标准实现会占用大量内存这与 Java、Python、JavaScript 等语言中的类组合有根本区别。为让 Rust Container 在无内容存储时可选内容只占用一个字的内存要把内容放到堆上如 Container3。前面提到的特殊优化也适用于 Option。回收内存的改动改动包括检测结构体何时无用让它们在父结构体中变为可选并移到堆上实现自定义的反序列化器不存储空的无用结构体。如 SmithyReference 结构体的改动同样 SmithyShape 也做了改动将所有 Option 替换为 Option存储所有反序列化的 AWS 形状所需的内存减少了一半节省了 475 MB。不过这种反序列化方式会消耗更多 CPU但减少内存占用让整个任务更快完成。大量使用 Box 会导致堆碎片化值得留意。验证证明影响有经验后会对节省空间有直觉但要严谨工作需检查改动是否有效并验证是否值得所以需要进行测量。在 Rust 中没有简单轻量的方法知道复合对象占用的总空间。解决方案是使用能提供自身状态信息的分配器使用了 jemalloc并比较反序列化前后的内存使用情况。在 Cargo.toml 中定义 “profile” 特性在 main.rs 中声明使用这个分配器接着在反序列化所有形状的函数中进行测量。[tikv_jemalloc_ctl](https://docs.rs/tikv-jemalloc-ctl/latest/tikv_jemalloc_ctl/stats/index.html) 提供了更多细节在服务器应用中可能会很有用。总结简要回顾要点每个 Rust 开发者需要理解并记住复合结构体可能会消耗大量内存通过检测字段内容是否无关紧要将 field: BigStruct 设为可选是值得的field: Option 即使在为 None 时也至少会占用 BigStruct 的空间可以使用 field: Option 打破这种内存占用模式使用 Serde 进行反序列化时这些优化仍然可行。