Hacker News 中文摘要

RSS订阅

巨型二进制文件 -- Huge Binaries

文章摘要

文章讨论了大型代码库中出现的巨大二进制文件问题,作者以亲身经历指出,在谷歌等公司中静态编译会导致超过25GiB的巨型二进制文件。这类似于"音障"问题,当代码规模超过x86_64架构的2GiB重定位限制时,就需要重新思考代码链接和构建方式。

文章总结

巨型二进制文件的挑战与解决方案

在攻读博士学位和提交学术论文期间,我遇到了一个特殊问题:为解决某些问题而构建的解决方案需要达到相当大的规模才能有效。审稿人常质疑这类问题是否存在,但实际上我在谷歌等企业环境中确实观察到过——只是无法引用这些案例。

巨型二进制文件现象

在超大型代码库中,一个独特问题是巨型二进制文件(ELF格式)。我曾见过包含调试符号超过25GiB的二进制文件。这种情况源于企业偏好静态构建服务以加速启动和简化部署——将全球最大代码库的所有代码静态包含,自然会产生庞大的二进制文件。

2GiB重定位屏障

就像音障一样,代码大小也存在临界点。对于x86_64架构,这个临界点是2GiB的"重定位屏障"。原因在于: - CALL指令使用32位有符号相对偏移量 - 最大寻址范围是±2GiB(2³¹位) - 当调用目标超过此范围时,会出现"重定位溢出"错误

解决方案:大型代码模型

最简单的解决方法是使用-mcmodel=large编译选项,它将: 1. 将相对调用改为64位绝对地址调用 2. 通过MOVABSCALL两条指令实现跳转

但这种方法存在明显缺点: - 指令膨胀:单个调用从5字节增至12字节 - 寄存器压力:需要占用一个通用寄存器(如%rdx) - 在包含数百万调用点的二进制中,这些开销会显著累积

替代策略

虽然大型代码模型可行,但理想情况是尽可能保持小型代码模型。其他优化策略包括: - 重构代码布局 - 使用函数指针表 - 采用分段加载机制

(作者表示将在后续文章中深入探讨这些方案)

本文技术细节通过LLVM的lld链接器演示,因其错误信息更清晰。所有示例代码采用CC-BY-SA许可。

查看原文改进建议

评论总结

以下是评论内容的总结:

  1. 标题修改建议

    • 有评论认为HN的标题去敏感化算法需要调整,原标题更直接。
      "The HN de-sensationalize algo for submission titles needs tweaking. Original title is simply 'Huge Binaries'."
  2. 对大二进制文件的担忧

    • 25GiB的单个二进制文件被认为不合理,建议使用动态链接。
      "25 GiB for a single binary sounds horrifying... at some point surely some dynamic linking is warranted"
    • 尽管静态编译简化部署,但超大二进制可能意味着代码结构问题。
      "surely if your actual executable code doesn't even fit in 2GB it's time to ask if that's really one binary's worth of code"
  3. 技术原因分析

    • 模板实例化(如Eigen库)和调试符号可能导致二进制膨胀。
      "Every math expression ends up as a new template instantiation."
    • 建议通过LTO(链接时优化)或分段编译消除死代码。
      "You should be using LTO for release builds... --gc-sections does a good job of culling dead code"
  4. 解决方案讨论

    • 使用-mcmodel=large或跳板(thunks)解决跳转限制,但可能影响性能。
      "Makes sense, but... there is not a single JMP instruction"
      "Though... it can be expensive to add trampolines, both in icache performance"
    • Facebook和Google通过代码布局优化(如BOLT)提升效率。
      "Move all the hot BBs near each other... Facebook's solution: [BOLT]"
  5. 实用性与折中

    • 静态编译工具链在故障时更可靠,但需权衡体积问题。
      "I keep on having the basic compile toolchain as statically compiled... It simply works better"

总结观点:大二进制文件引发对代码结构、工具链优化的讨论,支持静态部署的便利性,但普遍认为需通过动态链接、LTO或布局优化平衡体积与性能。