rust - 为什么使用 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 时犯了什么错误吗?
解决方案
什么是 LTO?
LTO 表示链接时间优化。它通常设置为使用用于生成目标文件的常规优化通道......在链接时代替,或者另外。
为什么这有关系?
编译器本身并不针对速度超过大小或大小超过速度进行优化;因此 LTO 也没有。
相反,当调用编译器时,用户选择一个配置文件。对于rustc
:
O0
,O1
,O2
并且O3
正在优化速度。Os
并且Oz
正在优化尺寸。
LTO 可以在任何优化级别之上组合,并将遵循选定的配置文件。
那么为什么尺寸会增加呢?
默认情况下,[release]
配置文件指示使用orcargo
调用,它尝试优化速度而不是大小。rustc
O2
O3
特别是,O3
可以相当依赖内联。内联就是为优化器提供更多上下文,因此有更多的优化机会...... LTO 提供了更多应用内联的机会(更多已知的函数),这里似乎发生了更多的内联。
那么为什么这篇博客文章声称它缩小了尺寸?
它还减小了尺寸。可能。
通过提供更多上下文,优化器/链接器可以意识到代码或依赖项的某些部分根本没有使用,因此可以省略。
如果使用Os
or Oz
,大小几乎肯定会下降。
如果使用O2
or O3
,未使用的代码会被删除,而内联会添加更多代码,因此最终结果是更大还是更小是完全不可预测的。
那么,LTO?
LTO 为优化器提供了更好的优化机会,因此它是 Releases 的一个很好的默认设置。
请记住,cargo
默认情况下倾向于速度而不是大小,如果这不适合您,您可能需要选择另一个优化方向。
推荐阅读
- python - 如何解析树中的常见孩子并在 Python 中给他们唯一的名字?
- angular - 如何在外部 html 文件中包含 Angular 应用程序
- excel - 如何重新分配 1 到 100 之间不重复的值范围?
- ruby-on-rails - 在rails中使用多个之前的操作
- javascript - 在VueJS中使用列表渲染时如何对列表进行排序
- c++ - 为什么循环无穷无尽?
- reactjs - 在上下文/提供者反应原生的异步函数中初始化状态
- neural-network - 如何获取pytorch网络的输入和最终输出
- reactjs - 未捕获(承诺)错误:当 Spring 应用程序托管在 localhost 上时,请求失败,状态码为 400
- php - 未定义索引:user_image in