Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【Rust 漫画】揭开 Hello World 二进制文件巨大之谜

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

作者头像
张汉东
发布于 2023-10-20 07:33:37
发布于 2023-10-20 07:33:37
1K00
代码可运行
举报
文章被收录于专栏:Rust 编程Rust 编程
运行总次数:0
代码可运行

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

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

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

漫画赏析

漫画解析

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
[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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2016年8月18日 Go生态洞察:Go 1.7版本二进制文件缩小
🐯 猫头虎博主为您呈现Go 1.7的新动向!Go 1.7的一个重要进步是二进制文件大小的显著减小,这对于部署在小型设备上的Go应用尤其重要。搜索词条:Go 1.7,二进制文件缩小。
猫头虎
2024/04/08
1000
2016年8月18日 Go生态洞察:Go 1.7版本二进制文件缩小
不要轻易使用 Alpine 镜像来构建 Docker 镜像,有坑!
第一部分着重介绍多阶段构建(multi-stage builds),因为这是镜像精简之路至关重要的一环。在这部分内容中,我会解释静态链接和动态链接的区别,它们对镜像带来的影响,以及如何避免那些不好的影响。中间会穿插一部分对 Alpine 镜像的介绍。链接:两个奇技淫巧,将 Docker 镜像体积减小 99%[1]
米开朗基杨
2020/05/26
27.2K0
Rust赋能前端:为WebAssembly 瘦身
大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder
前端柒八九
2025/01/03
910
Rust赋能前端:为WebAssembly 瘦身
一次Rust重写基础软件的实践(二)
受到2022年“谷歌使用Rust重写Android系统且所有Rust代码的内存安全漏洞为零” [1] 的启发,最近笔者怀着浓厚的兴趣也顺应Rust 的潮流,尝试着将一款C语言开发的基础软件转化为 Rust 语言。本文的主要目的是通过记录此次转化过程中遇到的比较常见且有意思的问题以及解决此问题的方法与大家一起做相关的技术交流和讨论。
MikeLoveRust
2024/01/24
2580
一次Rust重写基础软件的实践(二)
听GPT 讲Rust源代码--compiler(2)
在Rust源代码中,rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs文件的作用是为Cranelift代码生成器构建系统准备依赖项。
fliter
2024/03/07
1070
听GPT 讲Rust源代码--compiler(2)
在Linux环境中使用Go编译静态二进制文件[译]
Go语言的一个优势是能够生成静态链接的可执行程序。但是,这并不是说默认情况下编译出来的Go可执行程序都是静态链接的。在有些情况下,需要额外的操作才能实现。具体情况取决于操作系统,本文介绍Unix系统下如何达成这一目标。
数据小冰
2025/04/01
1030
在Linux环境中使用Go编译静态二进制文件[译]
【Rust日报】2023-11-21 如何将 Rust 的编译效率提高 75%
Rust经常被提到的一个痛点是编译时间较慢。为了享受借用检查器、安全性和零成本抽象等好处,我们需要花费更多时间进行编译。为了测试不同的更改,我们需要建立一个基准。我电脑的配置如下:
MikeLoveRust
2023/11/23
2K0
【Rust日报】2023-11-21 如何将 Rust 的编译效率提高 75%
Rust 性能评估与调优实践
本文将围绕 Rust 性能评估和调优主题,比较系统地介绍 Rust 代码的性能优化经验。先从大的总原则出发,介绍在编写 Rust 过程中应该遵循哪些原则对后续优化有帮助。接下来会分享一些代码优化的方法和技巧,然后介绍可以用于 Rust 代码性能评估的工具,也会包括 Rust专用的一些异步并发测试工具介绍。
张汉东
2022/01/04
2.5K0
Rust 性能评估与调优实践
Go高性能编程EP2: 通过upx 缩小可执行二进制文件的体积
我们都知道,Go有一个很重要的特点,那就是它的编译速度非常快,编译速度是Go语言设计的时候就重点考虑[1]的问题. 但是您有没有观察过Go语言编译后的二进制可执行文件的大小?我们先用一个简单的http server 的例子来看看。
萝卜要努力
2025/03/07
1260
Go高性能编程EP2:  通过upx 缩小可执行二进制文件的体积
【Rust学习】20_错误处理_panic!
错误是软件中不可避免的事实,因此Rust提供了许多特性来处理出现问题的情况。在许多情况下,Rust要求你在代码编译之前发现错误的可能性并采取一些行动。这个要求通过确保你在将代码部署到生产环境之前发现并适当处理错误,使你的程序更加健壮!
思索
2024/12/02
890
【Rust学习】20_错误处理_panic!
rust写操作系统 rCore tutorial 学习笔记:实验指导零 创建项目与启动
这是 os summer of code 2020 项目每日记录的一部分: 每日记录github地址(包含根据实验指导实现的每个阶段的代码):https://github.com/yunwei37/os-summer-of-code-daily
云微
2023/02/11
1.7K0
Rust实战系列-Rust介绍
看到这样的输出,就表示已经成功运行了 Rust 项目,尽管还没写任何代码。接下来看看发生了什么。
abin
2023/03/21
1.4K0
Rust实战系列-Rust介绍
通过禁止比较让 Go 二进制文件变小
大家常规的认知是,Go 程序中声明的类型越多,生成的二进制文件就越大。这个符合直觉,毕竟如果你写的代码不去操作定义的类型,那么定义一堆类型就没有意义了。然而,链接器的部分工作就是检测没有被程序引用的函数(比如说它们是一个库的一部分,其中只有一个子集的功能被使用),然后把它们从最后的编译产出中删除。常言道,“类型越多,二进制文件越大”,对于多数 Go 程序还是正确的。
用户8639654
2021/09/18
8550
减小镜像体积-docker最佳实践
当我们刚开始接触Docker,并尝试使用docker build构建镜像时,通常会构建出体积巨大的镜像。而事实上,我们可以通过一些技巧方法减小镜像的大小。本片博文,我将介绍一些优化技巧,同时也会探讨如何在减小镜像大小和可调试性取舍。这些技巧可以分为两部分:第一部分是多阶段构建(multi-stage builds), 正确使用多阶段构建能够极大减小构建物镜像的大小,同时还会解释静态链接(static link)和动态链接(dynamic link)之间的区别以及为什么我们需要了解它们;第二部分是使用一些常见的基础镜像,这些基础镜像仅包含我们所需要的内容,而无需引入其他文件。
Java宝典
2021/01/14
1.4K0
dotnet 进行二进制差分压缩文件
我需要对一个文件做二进制差分压缩,我有一个文件的起始点,在之后的每次更改我都记录文件的二进制的差分,这样就可以通过起始点和差分文件计算修改后的文件。通过二进制差分可以用来提高文件保存磁盘读写速度,也可以减少软件自动更新需要的文件大小
林德熙
2022/08/12
3360
6 种 WebAssembly 的优化手段
作者 | Matt Butcher, Radu Matei 译者 | 马可薇 策划 | 丁晓昀 简称为 Wasm 的 WebAssembly 是一种二进制格式,包括 Rust、C、JavaScript、Python、Ruby、.NET 在内等诸多语言都可通过 Wasm 执行。此外,Wasm 也可运行在各种硬件和操作系统之上,其规范的设计快速且紧凑,以及重中之重的安全。 在 2022 年,最初仅为浏览器设计的 Wasm 已经在其他领域大放异彩,实践证明,Wasm 在嵌入式编程、插件、云、边缘计算等领
深度学习与Python
2023/04/21
1.3K0
6 种 WebAssembly 的优化手段
【Rust学习】01_入门
让我们开始您的 Rust 之旅吧!有很多东西要学,但每一段旅程都是从第一步开始的,在本章中,我们将一起来学习以下知识点:
思索
2024/06/24
1440
【Rust学习】01_入门
Rust 1.51.0 已正式发布,及其新特性详述
2021 年 3 月 25 日,Rust 版本团队官宣发布新版本:1.51.0。
niqin.com
2022/06/30
1.3K0
Rust 1.51.0 已正式发布,及其新特性详述
go :gin 模板创建单个二进制文件
go get github.com/jessevdk/go-assets-builde
IT工作者
2022/07/25
5910
cargo manifest规则使用介绍
Cargo 是一个工具,允许 Rust 项目声明其各种依赖项,并确保您始终获得可重复的构建。
李小白是一只喵
2020/10/26
1.8K0
cargo manifest规则使用介绍
相关推荐
2016年8月18日 Go生态洞察:Go 1.7版本二进制文件缩小
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验