Rust | cargo build --release のバイナリサイズを削減する!
バイナリサイズを削減したい
cargo build --release
では、リリースモードでバイナリをビルドすることができます。
cargo build
は開発時の dev 仕様なので、最適化はされていません。
また、デバッグに関する情報も含まれています。
今回は、mocks という CLI ツールをビルドしてバイナリサイズを計測してみます。
What is mocks?
mocks
について、自分のブログでも紹介しているので、気になる方は見てくれると嬉しいです!
使用している外部クレートは以下です。
-
axum
- Web フレームワーク
-
clap
- CLI ツールのインターフェースを構築
-
serde_json
- JSON オブジェクトの操作
-
tokio
- 非同期ランタイム
debug と release で比較
まずは debug と release で比較してみます!
cargo build
では 9.2 M でした。
% du -h mocks
9.2M mocks
そして、cargo build --release
では 2.4 MB でした。
バイナリサイズにかなりの差があることがわかります🤔🤔
% du -h mocks
2.4M mocks
リリースプロファイルでビルドをカスタマイズする
Rust では、リリースプロファイルでビルドをカスタマイズすることで、
さらにビルドの最適化をすることができます。
結論から言うと 1.4 MB 以上 もバイナリサイズを削減することができました🥳🎉
半分以下のサイズに落ちています。
単位が M から K に変わっています!! 嬉しい!!
% du -h mocks
2.4M mocks
% du -h mocks
948K mocks
[profile.release] を定義する
今回のカスタマイズの内容を紹介します!
Cargo.toml に以下の [profile.release]
を定義しています。
[profile.release]
lto = true
opt-level = "s"
codegen-units = 1
panic = "abort"
strip = "symbols"
lto
Link Time Optimization (LOT) を有効化することができます。
デフォルトでは、Cargo はコンパイル・ユニットを個別にコンパイルし、最適化するよう指示します。
LTO は、リンク段階で最適化するようリンカーに指示します。
これにより、例えばデッドコードが削除され、バイナリサイズが削減されることがよくあるようです。
[profile.release]
lto = true
opt-level
サイズの最適化レベルを指定できます。
[profile.release]
opt-level = "s"
opt-level | プロファイルのデフォルト | |
---|---|---|
0 | 最適化なし | dev, test |
1 | 基本的な最適化 | |
2 | いくつかの最適化 | |
3 | 全ての最適化 | release, bench |
"s" | バイナリサイズの最適化 | |
"z" | バイナリサイズの最適化(ループのベクタライズをオフにする) |
codegen-units
Cargo はリリースビルドに 16 個の並列コード生成ユニットを指定します。
これによりコンパイル時間は短縮されますが、一部の最適化は行われません。
コード生成ユニットの数を 1 に限定することで、バイナリサイズの最適化を図ります。
ただ、この設定によりコンパイル時間が長くなる可能性があります。
[profile.release]
codegen-units = 1
デフォルトは codegen-units = 16
です。
panic
パニックが発生した際にバックトレースが生成されますが、これを強制終了させるように指定します。
[profile.release]
panic = "abort"
デフォルトは panic = "unwind"
です。
strip
Linux および macOS では、デフォルトでコンパイルされたファイルにシンボル情報が含まれています。
このシンボル情報は、バイナリを適切に実行するためには必要ありません。
以下のように指定することで、シンボル情報を削除することができます。
[profile.release]
strip = "symbols"
文字列でなく、真偽値 true
or false
で指定することも可能です。
String | Boolean |
---|---|
"symbols" | true |
"debuginfo" | |
"none" | false |
まとめ
公開・配布する CLI ツールのバイナリサイズを少しでも小さくしたくて、検証してみました🤝✨
無事に削減することができて、良かったです!!!!
ぜひ手元の Rust プロジェクトでサイズが削減される様子を確認しながら、
リリースプロファイルをカスタマイズしてみてください!
また、ツールの公開については以下の記事で紹介いるので、良ければ見ていってください💁♂️💁♂️
Discussion