前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Rust 漫画】揭开 Hello World 二进制文件巨大之谜

【Rust 漫画】揭开 Hello World 二进制文件巨大之谜

作者头像
张汉东
发布2023-10-20 15:33:37
5120
发布2023-10-20 15:33:37
举报
文章被收录于专栏:Rust 编程Rust 编程

创意:张汉东 绘画:ChatGPT DALL•E3

创意来源:本人学习 Rust 过程中的一些踩坑、成长与思考。

如果大家喜欢,欢迎点赞、转发和赞赏,每一位读者对认可是我持续创作的动力。

漫画赏析

漫画解析

当 Rust 新人写下第一个 Hello World 程序时:

代码语言:javascript
复制
fn main(){
    println!( "hello world, Rust");
}

在编译以后,看了二进制文件大小,多半会非常惊讶!你可能看到二进制文件大小高达 4 MB ,而 cpp 的 Hello world 二进制文件才 170kb,相比之下,Rust 二进制文件大小就太大了。

在 2015 年 Rust 1.0 发布之后的两三年内,这个问题曾在社区中引起了很大争议。

为什么 hello world 二进制文件如此巨大?

Rust语言在默认情况下产生较大的“Hello, World!”二进制文件的原因主要与其编译和链接策略有关。

  1. 静态链接
  • 默认情况下,Rust 产生的二进制是静态链接的,这意味着所有用到的库和函数都被直接包含在生成的文件中,而不是在运行时动态地加载。
  • 这一策略有其好处:生成的二进制文件在不同的系统上更具有独立性和可移植性,因为它不依赖于外部的库文件。但这也导致了较大的文件大小。
  • 即便是最简单的Rust程序,也会链接到Rust的标准库,也被称为std。这个库提供了许多基础的功能,如IO操作、线程管理、数据结构等。
  • 这些功能虽然在“Hello, World!”程序中可能未直接使用,但它们被包括在了编译的输出中。

其实 Rust的编译器(特别是其链接器)实际上是智能的,并采用了一个称为“树摇(tree shaking)”或“死代码消除(dead code elimination)”的过程,让它只会链接那些你的程序真正用到的库代码部分。

死代码消除:

  • Rust编译器会分析代码,确定哪些函数、变量和其他结构是未使用的。在编译和链接的过程中,所有未使用的代码(死代码)都不会出现在最终的二进制文件中。
  • Rust的标准库是模块化的。当你使用某个特定的模块或功能时,只有那部分代码会被拉入最终的二进制。例如,如果你的代码从标准库中只使用了 Vecprintln!,那么只有与这些功能相关的代码部分会被包括进来。
  • 静态链接的影响:尽管 Rust 进行了死代码消除,但静态链接仍然可能会导致较大的二进制文件,因为所有必要的代码都被包含在单个文件中。这与动态链接相反,其中二进制文件依赖于外部的共享库。
  • 其他因素:除了标准库和你的代码,还有其他因素可能影响编译输出的大小,例如调试信息、优化等级等。

那么该如何优化编译大小呢?

  1. 发布模式:通过使用cargo build --release,你可以告诉Rust进行更多的优化,并去除调试信息。这通常会显著减小生成的二进制文件大小。
  2. 去除标准库:对于某些特定应用,如嵌入式系统编程,你可能不需要整个标准库。在这种情况下,你可以考虑使用#![no_std]属性来禁用标准库。
  3. 使用strip命令strip是一个可以移除二进制文件中符号信息的工具,进一步减小文件大小。
  4. 其他优化工具和策略:例如,使用upx可以进一步压缩生成的二进制文件。还有其他的Cargo插件和工具,如cargo-bloat,可以帮助你识别和减小二进制文件大小。

社区也有人总结了如何优化编译文件大小:min-sized-rust[1]

其中也提供了一些优化配置:

代码语言:javascript
复制
[package]
name = "min-sized-rust"
version = "0.1.0"
authors = ["johnthagen <johnthagen@gmail.com>"]
license-file = "LICENSE.txt"

[dependencies]

[profile.release]
opt-level = "z"     # Optimize for size.
lto = true          # Enable Link Time Optimization
codegen-units = 1   # Reduce number of codegen units to increase optimizations.
panic = "abort"     # Abort on panic
strip = true        # Automatically strip symbols from the binary.

最终效果还是可以的。

后记

Rust 编译时间、编译文件大小和性能优化,也一个不可能三角,需要根据实际情况和需求进行权衡。

参考资料

[1]

min-sized-rust: https://github.com/johnthagen/min-sized-rust

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 觉学社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创意:张汉东 绘画:ChatGPT DALL•E3
  • 漫画赏析
  • 漫画解析
    • 为什么 hello world 二进制文件如此巨大?
      • 那么该如何优化编译大小呢?
      • 后记
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档