为什么使用LTO会增加Rust二进制文件的大小?

PEA*_*EAR 16 compiler-optimization rust lto

介绍

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

问题

cargo build --release没有进一步配置的情况下使用时,会生成2.942.744字节(= 2,8 MiB)的二进制数.我尝试通过启用链接时间优化(LTO)来优化这一点Cargo.toml:

[profile.release]
lto = true
Run Code Online (Sandbox Code Playgroud)

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

怎么解释这个?我配置Cargo有什么错吗?

Mat*_* M. 24

什么是LTO?

LTO意味着链路时间优化.它通常设置为使用用于生成目标文件的常规优化通道...在链接时,或者另外.

为什么这有关系?

编译器本身不会针对速度超过大小或大小来优化速度; LTO也不是.

相反,在调用编译器时,用户选择一个配置文件.用于rustc:

  • O0,O1,O2O3在优化速度.
  • OsOz正在优化尺寸.

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

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

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

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

那么为什么这篇博文宣称它缩小了尺寸呢?

它还减小了尺寸.有可能.

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

如果使用OsOz,尺寸几乎肯定会下降.

如果在内联时使用O2O3删除未使用的代码会添加更多代码,那么最终结果是更大还是更小是完全不可预测的.

那么,LTO?

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

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


Meh*_*dad 5

可能是因为内联,可以增加代码大小以提高速度.

  • LTO 真的能够内联函数吗?因为那需要重新编译那个特定的函数。你能提供一些文件吗? (2认同)