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

标签 rust compiler-optimization lto

简介

我完成了一个小型 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:

  • O0O1O2O3 正在优化速度。
  • OsOz 正在优化大小。

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

那么为什么尺寸变大了?

默认情况下,[release] 配置文件指示 cargo 使用 O2 调用 rustc O3尝试优化速度而不是大小。

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

那为什么this blog post声称它缩小了尺寸?

它还减小了尺寸。可能吧。

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

如果使用 OsOz,大小肯定会下降。

如果使用 O2O3,未使用的代码将被删除,同时内联会添加更多代码,因此最终结果是变大还是变小是不可预测的。

那么,LTO?

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

请记住,cargo 默认情况下倾向于速度而不是大小,如果这不适合您,您可能需要选择其他优化方向。

关于rust - 为什么使用 LTO 会增加我的 Rust 二进制文件的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52291006/

相关文章:

c++ - Clang、GCC 和 LTO 之间的互操作性

c - 编译器(通过链接时优化)如何处理快速返回的函数(提前退出路径)?

rust - 结构的生命周期边界如何在 Rust 中工作?

c# - C# 语言编译器是否自行执行任何实际优化?

c++ - 成员变量在赋值后保存垃圾值

optimization - SIMD 指令降低 CPU 频率

c++ - 使用 extern inline 时 G++ 发出 "storage class specified"错误

networking - rust 迹所有权问题

rust - 泛型函数中的 Rust 生命周期问题

multithreading - Rust mpsc::Sender 不能在线程间共享?