@@ -55,7 +55,7 @@ $ strip target/release/min-sized-rust
55
55
56
56
[ Cargo defaults its optimization level to ` 3 ` for release builds] [ cargo-profile ] ,
57
57
which optimizes the binary for ** speed** . To instruct Cargo to optimize for minimal binary
58
- ** size** , use the ` z ` optimization level in
58
+ ** size** , use the ` z ` optimization level in
59
59
[ ` Cargo.toml ` ] ( https://doc.rust-lang.org/cargo/reference/manifest.html ) :
60
60
61
61
[ cargo-profile ] : https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles
70
70
[ ` opt-level ` documentation] ( https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level ) :
71
71
72
72
> It is recommended to experiment with different levels to find the right balance for your project.
73
- There may be surprising results, such as ... the ` "s" ` and ` "z" ` levels not being necessarily
74
- smaller.
73
+ > There may be surprising results, such as ... the ` "s" ` and ` "z" ` levels not being necessarily
74
+ > smaller.
75
75
76
76
# Enable Link Time Optimization (LTO)
77
77
78
78
![ Minimum Rust: 1.0] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.0-brightgreen.svg )
79
79
80
- By default,
81
- [ Cargo instructs compilation units to be compiled and optimized in isolation] [ cargo-profile ] .
80
+ By default,
81
+ [ Cargo instructs compilation units to be compiled and optimized in isolation] [ cargo-profile ] .
82
82
[ LTO] ( https://llvm.org/docs/LinkTimeOptimization.html ) instructs the linker to optimize at the
83
83
link stage. This can, for example, remove dead code and often times reduces binary size.
84
84
@@ -94,14 +94,14 @@ lto = true
94
94
![ Minimum Rust: 1.28] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.28-brightgreen.svg )
95
95
![ Maximum Rust: 1.31] ( https://img.shields.io/badge/Maximum%20Rust%20Version-1.31-brightgreen.svg )
96
96
97
- As of Rust 1.32,
98
- [ ` jemalloc ` is removed by default] ( https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html ) .
99
- ** If using Rust 1.32 or newer, no action is needed to reduce binary size regarding this
97
+ As of Rust 1.32,
98
+ [ ` jemalloc ` is removed by default] ( https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html ) .
99
+ ** If using Rust 1.32 or newer, no action is needed to reduce binary size regarding this
100
100
feature** .
101
101
102
102
** Prior to Rust 1.32** , to improve performance on some platforms Rust bundled
103
- [ jemalloc] ( https://github.com/jemalloc/jemalloc ) , an allocator that often
104
- outperforms the default system allocator. Bundling jemalloc added around 200KB
103
+ [ jemalloc] ( https://github.com/jemalloc/jemalloc ) , an allocator that often
104
+ outperforms the default system allocator. Bundling jemalloc added around 200KB
105
105
to the resulting binary, however.
106
106
107
107
To remove ` jemalloc ` on Rust 1.28 - Rust 1.31, add this code to the top of ` main.rs ` :
@@ -116,7 +116,7 @@ static A: System = System;
116
116
# Reduce Parallel Code Generation Units to Increase Optimization
117
117
118
118
[ By default] [ cargo-profile ] , Cargo specifies 16 parallel codegen units for release builds.
119
- This improves compile times, but prevents some optimizations.
119
+ This improves compile times, but prevents some optimizations.
120
120
121
121
Set this to ` 1 ` in ` Cargo.toml ` to allow for maximum size reduction optimizations:
122
122
@@ -130,12 +130,12 @@ codegen-units = 1
130
130
![ Minimum Rust: 1.10] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.10-brightgreen.svg )
131
131
132
132
> ** Note** : Up to this point, the features discussed to reduce binary size did not have an
133
- impact on the behaviour of the program (only its execution speed). This feature does
134
- have an impact on behavior.
133
+ > impact on the behaviour of the program (only its execution speed). This feature does
134
+ > have an impact on behavior.
135
135
136
- [ By default] [ cargo-profile ] , when Rust code encounters a situation when it must call ` panic!() ` ,
137
- it unwinds the stack and produces a helpful backtrace. The unwinding code, however, does require
138
- extra binary size. ` rustc ` can be instructed to abort immediately rather than unwind, which
136
+ [ By default] [ cargo-profile ] , when Rust code encounters a situation when it must call ` panic!() ` ,
137
+ it unwinds the stack and produces a helpful backtrace. The unwinding code, however, does require
138
+ extra binary size. ` rustc ` can be instructed to abort immediately rather than unwind, which
139
139
removes the need for this extra unwinding code.
140
140
141
141
Enable this in ` Cargo.toml ` :
@@ -166,7 +166,7 @@ $ RUSTFLAGS="-Zlocation-detail=none" cargo +nightly build --release
166
166
![ Minimum Rust: Nightly] ( https://img.shields.io/badge/Minimum%20Rust%20Version-nightly-orange.svg )
167
167
168
168
> ** Note** : See also [ Xargo] ( https://github.com/japaric/xargo ) , the predecessor to ` build-std ` .
169
- [ Xargo is currently in maintenance status] ( https://github.com/japaric/xargo/issues/193 ) .
169
+ [ Xargo is currently in maintenance status] ( https://github.com/japaric/xargo/issues/193 ) .
170
170
171
171
> Example project is located in the [ ` build_std ` ] ( build_std ) folder.
172
172
@@ -179,10 +179,10 @@ aggressively optimize for size.
179
179
180
180
1 . The prebuilt ` libstd ` is optimized for speed, not size.
181
181
182
- 2 . It's not possible to remove portions of ` libstd ` that are not used in a particular application
182
+ 2 . It's not possible to remove portions of ` libstd ` that are not used in a particular application
183
183
(e.g. LTO and panic behaviour).
184
184
185
- This is where [ ` build-std ` ] ( https://doc.rust-lang.org/cargo/reference/unstable.html#build-std )
185
+ This is where [ ` build-std ` ] ( https://doc.rust-lang.org/cargo/reference/unstable.html#build-std )
186
186
comes in. The ` build-std ` feature is able to compile ` libstd ` with your application from the
187
187
source. It does this with the ` rust-src ` component that ` rustup ` conveniently provides.
188
188
@@ -214,7 +214,7 @@ On macOS, the final stripped binary size is reduced to 51KB.
214
214
![ Minimum Rust: Nightly] ( https://img.shields.io/badge/Minimum%20Rust%20Version-nightly-orange.svg )
215
215
216
216
Even if ` panic = "abort" ` is specified in ` Cargo.toml ` , ` rustc ` will still include panic strings
217
- and formatting code in final binary by default.
217
+ and formatting code in final binary by default.
218
218
[ An unstable ` panic_immediate_abort ` feature] ( https://github.com/rust-lang/rust/pull/55011 )
219
219
has been merged into the ` nightly ` ` rustc ` compiler to address this.
220
220
@@ -235,29 +235,27 @@ On macOS, the final stripped binary size is reduced to 30KB.
235
235
236
236
> Example project is located in the [ ` no_main ` ] ( no_main ) folder.
237
237
238
- > This section was contributed in part by [ @vi ] ( https://github.com/vi )
239
-
240
238
Up until this point, we haven't restricted what utilities we used from ` libstd ` . In this section
241
239
we will restrict our usage of ` libstd ` in order to reduce binary size further.
242
240
243
- If you want an executable smaller than 20 kilobytes, Rust's string formatting code,
244
- [ ` core::fmt ` ] ( https://doc.rust-lang.org/core/fmt/index.html ) must
245
- be removed. ` panic_immediate_abort ` only removes some usages of this code. There is a lot of other
241
+ If you want an executable smaller than 20 kilobytes, Rust's string formatting code,
242
+ [ ` core::fmt ` ] ( https://doc.rust-lang.org/core/fmt/index.html ) must
243
+ be removed. ` panic_immediate_abort ` only removes some usages of this code. There is a lot of other
246
244
code that uses formatting in some cases. That includes Rust's "pre-main" code in ` libstd ` .
247
245
248
- By using a C entry point (by adding the ` #![no_main] ` attribute) , managing stdio manually, and
249
- carefully analyzing which chunks of code you or your dependencies include, you can sometimes
246
+ By using a C entry point (by adding the ` #![no_main] ` attribute) , managing stdio manually, and
247
+ carefully analyzing which chunks of code you or your dependencies include, you can sometimes
250
248
make use of ` libstd ` while avoiding bloated ` core::fmt ` .
251
249
252
- Expect the code to be hacky and unportable, with more ` unsafe{} ` s than usual. It feels like
250
+ Expect the code to be hacky and unportable, with more ` unsafe{} ` s than usual. It feels like
253
251
` no_std ` , but with ` libstd ` .
254
252
255
- Start with an empty executable, ensure
256
- [ ` xargo bloat --release --target=... ` ] ( https://github.com/RazrFalcon/cargo-bloat ) contains no
257
- ` core::fmt ` or something about padding. Add (uncomment) a little bit. See that ` xargo bloat ` now
258
- reports drastically more. Review source code that you've just added. Probably some external crate or
253
+ Start with an empty executable, ensure
254
+ [ ` xargo bloat --release --target=... ` ] ( https://github.com/RazrFalcon/cargo-bloat ) contains no
255
+ ` core::fmt ` or something about padding. Add (uncomment) a little bit. See that ` xargo bloat ` now
256
+ reports drastically more. Review source code that you've just added. Probably some external crate or
259
257
a new ` libstd ` function is used. Recurse into that with your review process
260
- (it requires ` [replace] ` Cargo dependencies and maybe digging in ` libstd ` ), find out why it
258
+ (it requires ` [replace] ` Cargo dependencies and maybe digging in ` libstd ` ), find out why it
261
259
weighs more than it should. Choose alternative way or patch dependencies to avoid unnecessary
262
260
features. Uncomment a bit more of your code, debug exploded size with ` xargo bloat ` and so on.
263
261
@@ -306,8 +304,8 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! {
306
304
Up until this point, all size-reducing techniques were Rust-specific. This section describes
307
305
a language-agnostic binary packing tool that is an option to reduce binary size further.
308
306
309
- [ UPX] ( https://github.com/upx/upx ) is a powerful tool for creating a self contained, compressed
310
- binary with no addition runtime requirements. It claims to typically reduce binary size by 50-70%,
307
+ [ UPX] ( https://github.com/upx/upx ) is a powerful tool for creating a self- contained, compressed
308
+ binary with no addition runtime requirements. It claims to typically reduce binary size by 50-70%,
311
309
but the actual result depends on your executable.
312
310
313
311
``` bash
@@ -319,7 +317,7 @@ heuristic-based anti-virus software because malware often uses UPX.
319
317
320
318
# Tools
321
319
322
- - [ ` cargo-bloat ` ] ( https://github.com/RazrFalcon/cargo-bloat ) - Find out what takes most of the
320
+ - [ ` cargo-bloat ` ] ( https://github.com/RazrFalcon/cargo-bloat ) - Find out what takes most of the
323
321
space in your executable.
324
322
- [ ` cargo-unused-features ` ] ( https://github.com/TimonPost/cargo-unused-features ) - Find and prune
325
323
enabled but potentially unused feature flags from your project.
@@ -329,8 +327,8 @@ heuristic-based anti-virus software because malware often uses UPX.
329
327
330
328
# Containers
331
329
332
- Sometimes it's advantageous to deploy Rust into containers
333
- (e.g. [ Docker] ( https://www.docker.com/ ) ). There are several great existing resources to help
330
+ Sometimes it's advantageous to deploy Rust into containers
331
+ (e.g. [ Docker] ( https://www.docker.com/ ) ). There are several great existing resources to help
334
332
create minimum sized container images that run Rust binaries.
335
333
336
334
- [ Official ` rust:alpine ` image] ( https://hub.docker.com/_/rust )
@@ -359,20 +357,35 @@ create minimum sized container images that run Rust binaries.
359
357
- [ Shrinking ` .wasm ` Code Size] [ shrinking-wasm-code-size ]
360
358
361
359
[ 151-byte-static-linux-binary ] : https://mainisusuallyafunction.blogspot.com/2015/01/151-byte-static-linux-binary-in-rust.html
360
+
362
361
[ why-rust-binary-large ] : https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html
362
+
363
363
[ fmt-unreasonably-expensive ] : https://jamesmunns.com/blog/fmt-unreasonably-expensive/
364
+
364
365
[ tiny-windows-exe ] : https://www.codeslow.com/2019/12/tiny-windows-executable-in-rust.html
366
+
365
367
[ tiny-webassembly-graphics ] : https://cliffle.com/blog/bare-metal-wasm/
368
+
366
369
[ gstreamer-plugin ] : https://www.collabora.com/news-and-blog/blog/2020/04/28/reducing-size-rust-gstreamer-plugin/
370
+
367
371
[ optimizing-rust-binary-size ] : https://arusahni.net/blog/2020/03/optimizing-rust-binary-size.html
372
+
368
373
[ minimizing-mender-rust ] : https://mender.io/blog/building-mender-rust-in-yocto-and-minimizing-the-binary-size
374
+
369
375
[ optimize-with-cargo-and-semver ] : https://oknozor.github.io/blog/optimize-rust-binary-size/
376
+
370
377
[ tighten-rusts-belt ] : https://dl.acm.org/doi/abs/10.1145/3519941.3535075
378
+
371
379
[ avoiding-allocations-shrink-wasm ] : https://nickb.dev/blog/avoiding-allocations-in-rust-to-shrink-wasm-modules/
380
+
372
381
[ a-very-small-rust-binary ] : https://darkcoding.net/software/a-very-small-rust-binary-indeed/
382
+
373
383
[ dark-side-of-inlining ] : https://nickb.dev/blog/the-dark-side-of-inlining-and-monomorphization/
384
+
374
385
[ making-rust-binaries-smaller-by-default ] : https://kobzol.github.io/rust/cargo/2024/01/23/making-rust-binaries-smaller-by-default.html
386
+
375
387
[ min-sized-rust-windows ] : https://github.com/mcountryman/min-sized-rust-windows
388
+
376
389
[ shrinking-wasm-code-size ] : https://rustwasm.github.io/docs/book/reference/code-size.html
377
390
378
391
# Organizations
0 commit comments