首页 > 解决方案 > 为什么使用 LTO 会增加我的 Rust 二进制文件的大小?

问题描述

介绍

我完成了一个小型 Rust 项目(大约 300 行代码),它具有以下依赖项:

问题

cargo build --release没有进一步配置的情况下使用时,会生成一个 2.942.744 字节 (= 2,8 MiB) 的二进制文件。我试图通过在我的以下启用链接时间优化 (LTO) 来优化它Cargo.toml

[profile.release]
lto = true

令我惊讶的是,二进制文件增长了,新大小为 3.848.288 字节(= 3,7 MiB)。

这怎么解释?我在配置 Cargo 时犯了什么错误吗?

标签: rustcompiler-optimizationlto

解决方案


什么是 LTO?

LTO 表示链接时间优化。它通常设置为使用用于生成目标文件的常规优化通道......在链接时代替,或者另外。

为什么这有关系?

编译器本身并不针对速度超过大小或大小超过速度进行优化;因此 LTO 也没有。

相反,当调用编译器时,用户选择一个配置文件。对于rustc

  • O0, O1,O2并且O3正在优化速度。
  • Os并且Oz正在优化尺寸。

LTO 可以在任何优化级别之上组合,并将遵循选定的配置文件。

那么为什么尺寸会增加呢?

默认情况下,[release]配置文件指示使用orcargo调用,它尝试优化速度而不是大小。rustcO2O3

特别是,O3可以相当依赖内联。内联就是为优化器提供更多上下文,因此有更多的优化机会...... LTO 提供了更多应用内联的机会(更多已知的函数),这里似乎发生了更多的内联。

那么为什么这篇博客文章声称它缩小了尺寸?

它还减小了尺寸。可能。

通过提供更多上下文,优化器/链接器可以意识到代码或依赖项的某些部分根本没有使用,因此可以省略。

如果使用Osor Oz,大小几乎肯定会下降。

如果使用O2or O3,未使用的代码会被删除,而内联会添加更多代码,因此最终结果是更大还是更小是完全不可预测的。

那么,LTO?

LTO 为优化器提供了更好的优化机会,因此它是 Releases 的一个很好的默认设置。

请记住,cargo默认情况下倾向于速度而不是大小,如果这不适合您,您可能需要选择另一个优化方向。


推荐阅读