介绍
我完成了一个小的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意味着链接时间优化。通常将其设置为使用常规优化遍历,该遍历用于生成目标文件……在链接时或在链接时附加。
为什么这有关系?
编译器并没有针对速度超过大小或大小超过速度进行内在优化。因此,LTO也没有。
而是在调用编译器时,用户选择一个配置文件。对于rustc
:
O0
,O1
,O2
和O3
针对速度进行了优化。 Os
和Oz
正在优化大小。 LTO可以组合在任何优化级别之上,并且将遵循选定的配置文件。
那么为什么尺寸增加了呢?
默认情况下,
[release]
配置文件指示cargo
使用rustc
或O2
调用O3
,这会尝试针对大小上的速度进行优化。特别地,
O3
在很大程度上可以依赖于内联。内联是指为优化器提供更多的上下文,因此也提供了更多的优化机会... LTO提供了更多的机会来应用内联(更多已知的函数),并且这里似乎发生了更多的内联。那么,为什么this blog post声称它减小了尺寸呢?
它还减小了尺寸。可能吧。
通过提供更多的上下文,优化器/链接器可以意识到根本不使用部分代码或依赖项,因此可以省去。
如果使用
Os
或Oz
,则大小一定会减小。如果使用
O2
或O3
,则删除未使用的代码,而内联会添加更多代码,因此最终结果是较大还是较小是非常不可预测的。那么,LTO?
LTO为优化器提供了更好的优化机会,因此它是Releases的理想默认设置。
请记住,默认情况下
cargo
倾向于速度超过大小,如果这不适合您,则可能需要选择另一个优化方向。关于rust - 为什么使用LTO会增加Rust二进制文件的大小?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52291006/