次の依存関係を持つ小さなRustプロジェクト(約300行のコード))を終了しました:
追加の設定なしでcargo build --release
を使用すると、2.942.744バイト(= 2,8 MiB)のバイナリが生成されます。私のCargo.toml
でリンク時最適化(LTO)を有効にして、これを最適化しようとしました:
[profile.release]
lto = true
驚いたことに、バイナリのサイズは大きくなり、新しいサイズは3.848.288バイト(= 3,7 MiB)になりました。
これはどのように説明できますか? Cargoの設定に間違いはありますか?
LTOはリンク時最適化を意味します。これは通常、オブジェクトファイルの作成に使用される通常の最適化パスを使用するように設定されています...リンク時に、代わりに、または追加で。
コンパイラーは、本質的にサイズよりも速度またはサイズよりも速度を優先して最適化しません。したがって、LTOも行いません。
代わりに、コンパイラーを呼び出すときに、ユーザーはプロファイルを選択します。 rustc
の場合:
O0
、O1
、O2
およびO3
は速度を最適化しています。Os
とOz
はサイズを最適化しています。LTOは任意の最適化レベルの上に組み合わせることができ、選択したプロファイルに従います。
デフォルトでは、[release]
プロファイルはcargo
にrustc
をO2
またはO3
で呼び出すように指示します。これはattemptsサイズよりも速度を最適化します。
特に、O3
は、インライン化に大きく依存しています。インライン化とは、オプティマイザにより多くのコンテキストを与えること、したがって最適化の機会を増やすことです。LTOは、インライン化(より既知の関数)を適用する機会を提供します。
サイズも小さくなります。たぶん。
より多くのコンテキストを提供することにより、オプティマイザー/リンカーは、コードの一部または依存関係がまったく使用されないことを認識できるため、省略できます。
Os
またはOz
を使用している場合、サイズは確実に減少します。
O2
またはO3
を使用すると、インライン化中に未使用のコードが削除され、コードが追加されるため、最終結果が大きいか小さいかはまったく予測できません。
LTOはオプティマイザに最適化の機会を提供するため、リリースのデフォルトとして適しています。
cargo
はデフォルトでサイズよりも速度が優先されることに注意してください。これが適切でない場合は、別の最適化方向を選択することをお勧めします。
おそらくインライン化が原因で、コードサイズを増やして速度を上げることができます。