@@ -55,7 +55,7 @@ $ strip target/release/min-sized-rust
5555
5656[ Cargo defaults its optimization level to ` 3 ` for release builds] [ cargo-profile ] ,
5757which 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
5959[ ` Cargo.toml ` ] ( https://doc.rust-lang.org/cargo/reference/manifest.html ) :
6060
6161[ cargo-profile ] : https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles
7070[ ` opt-level ` documentation] ( https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level ) :
7171
7272> 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.
7575
7676# Enable Link Time Optimization (LTO)
7777
7878![ Minimum Rust: 1.0] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.0-brightgreen.svg )
7979
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 ] .
8282[ LTO] ( https://llvm.org/docs/LinkTimeOptimization.html ) instructs the linker to optimize at the
8383link stage. This can, for example, remove dead code and often times reduces binary size.
8484
@@ -94,14 +94,14 @@ lto = true
9494![ Minimum Rust: 1.28] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.28-brightgreen.svg )
9595![ Maximum Rust: 1.31] ( https://img.shields.io/badge/Maximum%20Rust%20Version-1.31-brightgreen.svg )
9696
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
100100feature** .
101101
102102** 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
105105to the resulting binary, however.
106106
107107To 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;
116116# Reduce Parallel Code Generation Units to Increase Optimization
117117
118118[ 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.
120120
121121Set this to ` 1 ` in ` Cargo.toml ` to allow for maximum size reduction optimizations:
122122
@@ -130,12 +130,12 @@ codegen-units = 1
130130![ Minimum Rust: 1.10] ( https://img.shields.io/badge/Minimum%20Rust%20Version-1.10-brightgreen.svg )
131131
132132> ** 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.
135135
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
139139removes the need for this extra unwinding code.
140140
141141Enable this in ` Cargo.toml ` :
@@ -166,7 +166,7 @@ $ RUSTFLAGS="-Zlocation-detail=none" cargo +nightly build --release
166166![ Minimum Rust: Nightly] ( https://img.shields.io/badge/Minimum%20Rust%20Version-nightly-orange.svg )
167167
168168> ** 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 ) .
170170
171171> Example project is located in the [ ` build_std ` ] ( build_std ) folder.
172172
@@ -179,10 +179,10 @@ aggressively optimize for size.
179179
1801801 . The prebuilt ` libstd ` is optimized for speed, not size.
181181
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
183183 (e.g. LTO and panic behaviour).
184184
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 )
186186comes in. The ` build-std ` feature is able to compile ` libstd ` with your application from the
187187source. It does this with the ` rust-src ` component that ` rustup ` conveniently provides.
188188
@@ -214,7 +214,7 @@ On macOS, the final stripped binary size is reduced to 51KB.
214214![ Minimum Rust: Nightly] ( https://img.shields.io/badge/Minimum%20Rust%20Version-nightly-orange.svg )
215215
216216Even 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.
218218[ An unstable ` panic_immediate_abort ` feature] ( https://github.com/rust-lang/rust/pull/55011 )
219219has been merged into the ` nightly ` ` rustc ` compiler to address this.
220220
@@ -235,29 +235,27 @@ On macOS, the final stripped binary size is reduced to 30KB.
235235
236236> Example project is located in the [ ` no_main ` ] ( no_main ) folder.
237237
238- > This section was contributed in part by [ @vi ] ( https://github.com/vi )
239-
240238Up until this point, we haven't restricted what utilities we used from ` libstd ` . In this section
241239we will restrict our usage of ` libstd ` in order to reduce binary size further.
242240
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
246244code that uses formatting in some cases. That includes Rust's "pre-main" code in ` libstd ` .
247245
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
250248make use of ` libstd ` while avoiding bloated ` core::fmt ` .
251249
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
253251` no_std ` , but with ` libstd ` .
254252
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
259257a 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
261259weighs more than it should. Choose alternative way or patch dependencies to avoid unnecessary
262260features. Uncomment a bit more of your code, debug exploded size with ` xargo bloat ` and so on.
263261
@@ -306,8 +304,8 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! {
306304Up until this point, all size-reducing techniques were Rust-specific. This section describes
307305a language-agnostic binary packing tool that is an option to reduce binary size further.
308306
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%,
311309but the actual result depends on your executable.
312310
313311``` bash
@@ -319,7 +317,7 @@ heuristic-based anti-virus software because malware often uses UPX.
319317
320318# Tools
321319
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
323321 space in your executable.
324322- [ ` cargo-unused-features ` ] ( https://github.com/TimonPost/cargo-unused-features ) - Find and prune
325323 enabled but potentially unused feature flags from your project.
@@ -329,8 +327,8 @@ heuristic-based anti-virus software because malware often uses UPX.
329327
330328# Containers
331329
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
334332create minimum sized container images that run Rust binaries.
335333
336334- [ Official ` rust:alpine ` image] ( https://hub.docker.com/_/rust )
@@ -359,20 +357,35 @@ create minimum sized container images that run Rust binaries.
359357- [ Shrinking ` .wasm ` Code Size] [ shrinking-wasm-code-size ]
360358
361359[ 151-byte-static-linux-binary ] : https://mainisusuallyafunction.blogspot.com/2015/01/151-byte-static-linux-binary-in-rust.html
360+
362361[ why-rust-binary-large ] : https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html
362+
363363[ fmt-unreasonably-expensive ] : https://jamesmunns.com/blog/fmt-unreasonably-expensive/
364+
364365[ tiny-windows-exe ] : https://www.codeslow.com/2019/12/tiny-windows-executable-in-rust.html
366+
365367[ tiny-webassembly-graphics ] : https://cliffle.com/blog/bare-metal-wasm/
368+
366369[ gstreamer-plugin ] : https://www.collabora.com/news-and-blog/blog/2020/04/28/reducing-size-rust-gstreamer-plugin/
370+
367371[ optimizing-rust-binary-size ] : https://arusahni.net/blog/2020/03/optimizing-rust-binary-size.html
372+
368373[ minimizing-mender-rust ] : https://mender.io/blog/building-mender-rust-in-yocto-and-minimizing-the-binary-size
374+
369375[ optimize-with-cargo-and-semver ] : https://oknozor.github.io/blog/optimize-rust-binary-size/
376+
370377[ tighten-rusts-belt ] : https://dl.acm.org/doi/abs/10.1145/3519941.3535075
378+
371379[ avoiding-allocations-shrink-wasm ] : https://nickb.dev/blog/avoiding-allocations-in-rust-to-shrink-wasm-modules/
380+
372381[ a-very-small-rust-binary ] : https://darkcoding.net/software/a-very-small-rust-binary-indeed/
382+
373383[ dark-side-of-inlining ] : https://nickb.dev/blog/the-dark-side-of-inlining-and-monomorphization/
384+
374385[ making-rust-binaries-smaller-by-default ] : https://kobzol.github.io/rust/cargo/2024/01/23/making-rust-binaries-smaller-by-default.html
386+
375387[ min-sized-rust-windows ] : https://github.com/mcountryman/min-sized-rust-windows
388+
376389[ shrinking-wasm-code-size ] : https://rustwasm.github.io/docs/book/reference/code-size.html
377390
378391# Organizations
0 commit comments