我完成了一个带有以下依赖项的小型Rust项目(大约300行代码):
在没有进一步配置的情况下使用cargo build --release
时,会生成2.942.744字节(= 2,8 MiB)的二进制数。我尝试通过在Cargo.toml
中启用链接时间优化(LTO)来优化它:
[profile.release]
lto = true
令我惊讶的是,二进制文件增长了,新的大小为3.848.288字节(= 3,7 MiB)。
怎么解释这个?我配置Cargo有什么错吗?
LTO意味着链路时间优化。它通常设置为使用用于生成目标文件的常规优化通道...在链接时,或者另外。
编译器本身不会针对速度超过大小或大小来优化速度; LTO也不是。
相反,在调用编译器时,用户选择一个配置文件。对于rustc
:
O0
,O1
,O2
和O3
正在优化速度。Os
和Oz
正在优化尺寸。LTO可以在任何优化级别之上进行组合,并将遵循所选的配置文件。
默认情况下,[release]
配置文件指示cargo
使用rustc
或O2
调用O3
,它试图优化速度而不是大小。
特别是,O3
可以非常依赖内联。内联就是为优化器提供更多上下文,因此有更多优化机会...... LTO提供了更多应用内联的机会(更多已知函数),并且在这里似乎发生了更多的内联。
它还减小了尺寸。有可能。
通过提供更多上下文,优化器/链接器可以意识到代码或依赖项的某些部分根本不被使用,因此可以省略。
如果使用Os
或Oz
,大小几乎肯定会下降。
如果使用O2
或O3
,删除未使用的代码,同时内联添加更多代码,因此最终结果是更大还是更小是无法预测的。
LTO为优化器提供了更好的优化机会,因此它是Releases的一个很好的默认值。
请记住,默认情况下,cargo
倾向于速度超过大小,如果这不适合您,您可能想要选择另一个优化方向。
可能是因为内联,可以增加代码大小以提高速度。