LoginSignup
24
14

More than 5 years have passed since last update.

cargo-bloatでRustのバイナリサイズの原因を特定する

Last updated at Posted at 2018-01-11

最近Redditでちょっと話題になっていたcargo-bloatを紹介。

Cargo-bloat

どの関数が重いかがざっくりわかるCargo Subcommand
こんな感じになります。

$ cargo bloat --release -n 10
    Finished ...

  File  .text     Size Name
 39.1%  72.8%   1.5MiB [3469 Others]
  3.5%   6.4% 132.1KiB clap::app::parser::Parser::add_defaults
  2.3%   4.3%  88.7KiB clap::app::parser::Parser::add_env
  1.5%   2.8%  56.9KiB <regex::exec::ExecNoSync<'c> as regex::re_trait::Regu...
  1.3%   2.4%  50.0KiB clap::app::parser::Parser::get_matches_with
  1.3%   2.4%  49.8KiB clap::app::parser::Parser::parse_long_arg
  1.3%   2.4%  49.1KiB clap::app::parser::Parser::parse_short_arg
  1.1%   2.0%  40.2KiB rg::args::ArgMatches::to_args
  0.9%   1.7%  34.5KiB regex_syntax::parser::Parser::parse_expr
  0.9%   1.6%  33.4KiB clap::app::validator::Validator::validate_matched_args
  0.7%   1.3%  25.8KiB encoding_rs::variant::VariantDecoder::decode_to_utf8_raw
 53.8% 100.0%   2.0MiB .text section size, the file size is 3.7MiB

How to Use

Install

まだcrates.ioには置いていないのでgitを介してinstallする感じになる。

cargo install --force --git https://github.com/RazrFalcon/cargo-bloat.git

2017/1/12追記: Publishされました

cargo install cargo-bloat

Command

$ cargo bloat -V
cargo-bloat 0.1.0
$ cargo bloat -h
Find out what takes most of the space in your executable

Usage: cargo bloat [options]

Options:
    -h, --help              Print this message
    -V, --version           Print version info and exit
    --features FEATURES     Space-separated list of features to also build
    --all-features          Build all available features
    --no-default-features   Do not build the `default` feature
    --manifest-path PATH    Path to the manifest to analyze
    --release               Build artifacts in release mode, with optimizations
    --example NAME          Build only the specified example
    --crates                Per crate bloatedness
    --filter CRATE          Filter functions by crate
    --split-std             Split the 'std' crate to original crates like core, alloc, etc.
    --full-fn               Print full function name with hash values
    -n NUM                  Number of lines to show, 0 to show all [default: 20]
    -w, --wide              Do not trim long function names
    -v, --verbose           Use verbose output
    -q, --quiet             No output printed to stdout
    --color WHEN            Coloring: auto, always, never
    --frozen                Require Cargo.lock and cache are up to date
    --locked                Require Cargo.lock is up to date
    -Z FLAG ...             Unstable (nightly-only) flags to Cargo

見慣れないオプションがいくつかある。

--crates                Per crate bloatedness
--filter CRATE          Filter functions by crate
--split-std             Split the 'std' crate to original crates like core, alloc, etc.
--full-fn               Print full function name with hash values
-n NUM                  Number of lines to show, 0 to show all [default: 20]
-w, --wide              Do not trim long function names

使用例

お世話になっているripgrepに使ってみる。

$ git clone https://github.com/BurntSushi/ripgrep
$ cd ripgrep
$ cargo bloat --release
    Compiling ...
    Finished ...

  File  .text     Size Name
 34.5%  64.1%   1.3MiB [3459 Others]
  3.5%   6.4% 132.1KiB clap::app::parser::Parser::add_defaults
  2.3%   4.3%  88.7KiB clap::app::parser::Parser::add_env
  1.5%   2.8%  56.9KiB <regex::exec::ExecNoSync<'c> as regex::re_trait::Regu...
  1.3%   2.4%  50.0KiB clap::app::parser::Parser::get_matches_with
  1.3%   2.4%  49.8KiB clap::app::parser::Parser::parse_long_arg
  1.3%   2.4%  49.1KiB clap::app::parser::Parser::parse_short_arg
  1.1%   2.0%  40.2KiB rg::args::ArgMatches::to_args
  0.9%   1.7%  34.5KiB regex_syntax::parser::Parser::parse_expr
  0.9%   1.6%  33.4KiB clap::app::validator::Validator::validate_matched_args
  0.7%   1.3%  25.8KiB encoding_rs::variant::VariantDecoder::decode_to_utf8_raw
  0.7%   1.2%  25.5KiB globset::GlobSet::new
  0.6%   1.2%  23.7KiB rg::run
  0.5%   0.9%  18.6KiB regex::re_bytes::Regex::find_at
  0.5%   0.9%  18.5KiB <regex::re_trait::Matches<'t, R> as core::iter::itera...
  0.5%   0.9%  17.9KiB ignore::walk::Worker::run
  0.4%   0.8%  15.6KiB rg::app::app
  0.4%   0.7%  15.1KiB clap::app::help::Help::write_arg
  0.4%   0.7%  15.0KiB rg::run_one_thread
  0.4%   0.7%  14.9KiB clap::app::usage::get_required_usage_from
  0.4%   0.7%  13.8KiB clap::app::validator::Validator::validate
 53.8% 100.0%   2.0MiB .text section size, the file size is 3.7MiB

普通に打つとこんな感じ。デフォルトではトップ20が表示され、その他は一つにまとめられる。コマンドラインパーサのclapが目立つ。
Sizeは.textセクションのもの。%はファイル全体に対してと.textセクションの合計に対しての両方を出してくれるようになった。

20は多いので-n 10でトップ10だけ表示することにする。これが上に載せた例。

$ cargo bloat --release -n 10
    Finished ...

  File  .text     Size Name
 39.1%  72.8%   1.5MiB [3469 Others]
  3.5%   6.4% 132.1KiB clap::app::parser::Parser::add_defaults
  2.3%   4.3%  88.7KiB clap::app::parser::Parser::add_env
  1.5%   2.8%  56.9KiB <regex::exec::ExecNoSync<'c> as regex::re_trait::Regu...
  1.3%   2.4%  50.0KiB clap::app::parser::Parser::get_matches_with
  1.3%   2.4%  49.8KiB clap::app::parser::Parser::parse_long_arg
  1.3%   2.4%  49.1KiB clap::app::parser::Parser::parse_short_arg
  1.1%   2.0%  40.2KiB rg::args::ArgMatches::to_args
  0.9%   1.7%  34.5KiB regex_syntax::parser::Parser::parse_expr
  0.9%   1.6%  33.4KiB clap::app::validator::Validator::validate_matched_args
  0.7%   1.3%  25.8KiB encoding_rs::variant::VariantDecoder::decode_to_utf8_raw
 53.8% 100.0%   2.0MiB .text section size, the file size is 3.7MiB

clapが重いのは明らかだが、--cratesオプションを渡して確認する。

$ cargo bloat --release --crates
    Finished ...

  File  .text     Size Name
 15.3%  28.4% 584.0KiB clap
 11.1%  20.7% 426.1KiB [Unknown]
 10.7%  20.0% 410.5KiB std
  6.2%  11.5% 236.5KiB regex
  3.4%   6.4% 131.1KiB regex_syntax
  2.5%   4.7%  96.7KiB ignore
  1.3%   2.5%  50.8KiB globset
  0.8%   1.4%  29.3KiB encoding_rs
  0.5%   0.9%  19.0KiB grep
  0.4%   0.8%  17.1KiB walkdir
  0.3%   0.6%  11.8KiB aho_corasick
  0.2%   0.4%   8.0KiB crossbeam
  0.2%   0.3%   6.0KiB env_logger
  0.2%   0.3%   6.0KiB thread_local
  0.1%   0.2%   5.1KiB termcolor
  0.1%   0.2%   3.2KiB ansi_term
  0.1%   0.1%   2.8KiB vec_map
  0.1%   0.1%   2.1KiB utf8_ranges
  0.1%   0.1%   2.1KiB memchr
  0.1%   0.1%   2.0KiB strsim
 53.8% 100.0%   2.0MiB .text section size, the file size is 3.7MiB

28%をclapが占めているという状態。高機能なだけになかなか重い。

軽量版clapを使う

ここでclapv2.29.1を使うようにcargo updateしてからもう一度実行してみる。

$ cargo bloat --release --crates
    Finished ...

  File  .text     Size Name
 12.2%  24.8% 423.5KiB [Unknown]
 11.7%  23.8% 406.8KiB std
  7.0%  14.3% 244.0KiB clap
  6.8%  13.8% 236.7KiB regex
  3.8%   7.7% 131.1KiB regex_syntax
  2.8%   5.7%  96.7KiB ignore
  1.5%   3.0%  50.8KiB globset
  0.8%   1.7%  29.3KiB encoding_rs
  0.5%   1.1%  19.0KiB grep
  0.5%   1.0%  17.1KiB walkdir
  0.3%   0.7%  11.8KiB aho_corasick
  0.2%   0.5%   8.0KiB crossbeam
  0.2%   0.4%   6.0KiB env_logger
  0.2%   0.3%   6.0KiB thread_local
  0.1%   0.3%   5.1KiB termcolor
  0.1%   0.2%   3.2KiB ansi_term
  0.1%   0.2%   2.8KiB vec_map
  0.1%   0.1%   2.1KiB utf8_ranges
  0.1%   0.1%   2.1KiB memchr
  0.1%   0.1%   2.0KiB strsim
 49.2% 100.0%   1.7MiB .text section size, the file size is 3.4MiB

300Kほど軽くなっている。
実は、clapの開発者がcargo-bloatの結果に触発されて軽量化を行ったらしい。開発途中だけど、こんな感じで参考になりそう。

2017/01/12追加: stdライブラリを分割して表示

1/11夜にオプションがいくつか追加されたので--split-stdを使ってみた。--filterとかは自明なので割愛。

$ cargo bloat --release --crates --split-std
    Finished ...

  File  .text     Size Name
 12.2%  24.8% 423.5KiB [Unknown]
  7.0%  14.3% 244.0KiB clap
  6.8%  13.8% 236.7KiB regex
  5.5%  11.2% 191.5KiB core
  3.8%   7.7% 131.1KiB regex_syntax
  3.4%   7.0% 119.6KiB std
  2.8%   5.7%  96.7KiB ignore
  2.6%   5.3%  91.4KiB alloc
  1.5%   3.0%  50.8KiB globset
  0.8%   1.7%  29.3KiB encoding_rs
  0.5%   1.1%  19.0KiB grep
  0.5%   1.0%  17.1KiB walkdir
  0.3%   0.7%  11.8KiB aho_corasick
  0.2%   0.5%   8.0KiB crossbeam
  0.2%   0.4%   6.0KiB env_logger
  0.2%   0.3%   6.0KiB thread_local
  0.1%   0.3%   5.1KiB termcolor
  0.1%   0.2%   3.2KiB std_unicode
  0.1%   0.2%   3.2KiB ansi_term
  0.1%   0.2%   2.8KiB vec_map
 49.2% 100.0%   1.7MiB .text section size, the file size is 3.4MiB

stdライブラリがcoreallocなどのcrateに分割されて表示されているのがわかる。

注意点

  • RustではなくCで書かれたライブラリ等は[Unknown]にまとめられる
  • Windows未対応
24
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
14