为什么使用 LTO 会增加我的 Rust 二进制文件的大小?
Why does using LTO increase the size of my Rust binary?
简介
我完成了一个小的 Rust 项目(大约 300 行代码),依赖如下:
问题
在没有进一步配置的情况下使用 cargo build --release
时,会生成一个 2.942.744 字节(= 2,8 MiB)的二进制文件。我试图通过在 Cargo.toml
:
中启用 Link 时间优化 (LTO) 来优化它
[profile.release]
lto = true
令我惊讶的是,二进制文件增长了,新的大小为 3.848.288 字节 (= 3,7 MiB)。
这怎么解释?我配置 Cargo 有什么错误吗?
可能是因为内联,它可以增加代码大小以提高速度。
什么是 LTO?
LTO 表示 Link-时间优化。通常将其设置为使用用于生成目标文件的常规优化过程......在 link 时间代替,或者另外。
为什么重要?
编译器本身并不会针对速度超过大小或大小超过速度进行优化;因此 LTO 也没有。
相反,当调用编译器时,用户 select 是一个配置文件。对于 rustc
:
O0
、O1
、O2
和 O3
正在优化速度。
Os
和 Oz
正在优化尺寸。
LTO 可以组合在任何优化级别之上,并将遵循 selected 配置文件。
为什么尺寸变大了?
默认情况下,[release]
配置文件指示 cargo
使用 O2
或 O3
调用 rustc
, 尝试 优化速度超过大小。
特别是,O3
可以非常依赖内联。内联就是为优化器提供更多上下文,从而提供更多优化机会......LTO 提供了更多应用内联的机会(更多已知函数),这里似乎发生了更多内联。
那么为什么 this blog post 声称它缩小了尺寸?
它还可以减小尺寸。有可能。
通过提供更多上下文,optimizer/linker 可以意识到某些部分代码或依赖项根本没有被使用,因此可以省略。
如果使用Os
或Oz
,尺寸几乎肯定会下降。
如果使用 O2
或 O3
,未使用的代码将被删除,而内联会添加更多代码,因此最终结果是变大还是变小很难预测。
那么,LTO?
LTO 为优化器提供了更好的优化机会,因此它是发布的一个很好的默认设置。
请记住 cargo
默认情况下倾向于速度超过大小,如果这不适合您,您可能需要 select 另一个优化方向。
简介
我完成了一个小的 Rust 项目(大约 300 行代码),依赖如下:
问题
在没有进一步配置的情况下使用 cargo build --release
时,会生成一个 2.942.744 字节(= 2,8 MiB)的二进制文件。我试图通过在 Cargo.toml
:
[profile.release]
lto = true
令我惊讶的是,二进制文件增长了,新的大小为 3.848.288 字节 (= 3,7 MiB)。
这怎么解释?我配置 Cargo 有什么错误吗?
可能是因为内联,它可以增加代码大小以提高速度。
什么是 LTO?
LTO 表示 Link-时间优化。通常将其设置为使用用于生成目标文件的常规优化过程......在 link 时间代替,或者另外。
为什么重要?
编译器本身并不会针对速度超过大小或大小超过速度进行优化;因此 LTO 也没有。
相反,当调用编译器时,用户 select 是一个配置文件。对于 rustc
:
O0
、O1
、O2
和O3
正在优化速度。Os
和Oz
正在优化尺寸。
LTO 可以组合在任何优化级别之上,并将遵循 selected 配置文件。
为什么尺寸变大了?
默认情况下,[release]
配置文件指示 cargo
使用 O2
或 O3
调用 rustc
, 尝试 优化速度超过大小。
特别是,O3
可以非常依赖内联。内联就是为优化器提供更多上下文,从而提供更多优化机会......LTO 提供了更多应用内联的机会(更多已知函数),这里似乎发生了更多内联。
那么为什么 this blog post 声称它缩小了尺寸?
它还可以减小尺寸。有可能。
通过提供更多上下文,optimizer/linker 可以意识到某些部分代码或依赖项根本没有被使用,因此可以省略。
如果使用Os
或Oz
,尺寸几乎肯定会下降。
如果使用 O2
或 O3
,未使用的代码将被删除,而内联会添加更多代码,因此最终结果是变大还是变小很难预测。
那么,LTO?
LTO 为优化器提供了更好的优化机会,因此它是发布的一个很好的默认设置。
请记住 cargo
默认情况下倾向于速度超过大小,如果这不适合您,您可能需要 select 另一个优化方向。