razrfalcon / cargo-bloat Goto Github PK
View Code? Open in Web Editor NEWFind out what takes most of the space in your executable.
License: MIT License
Find out what takes most of the space in your executable.
License: MIT License
This would be quite handy, as I'm occasionally having to track down changes in a particular library, especially ones that may be contributing to the build time and size of its generated test suite.
Is there way to support no-std envs? Architectures such as ARM would be nice, too, but I guess thats not trivial?
When trying to determine what dependencies are contributing to the size of https://github.com/mozilla/mentat/ (after cd tools/cli, for example), cargo bloat --release
indicates that most of them are coming from syn
. Filtering to the mentat
crate gives zero results.
It seems to be finding the executable that implements a procedural macro (in this case for failure_derive
).
Explicitly passing --bin mentat_cli
causes it to report correct information.
Currently cargo bloat
support grouping by:
I think it would be helpful it cargo bloat
could also group by:
I think that's important because I have lots of symbols like:
0.1% 0.3% 9.2KiB protobuf <protobuf::descriptor::FileOptions as protobuf::core::Message>::merge_from
0.1% 0.2% 7.7KiB protobuf <protobuf::descriptor::FileOptions as protobuf::core::Message>::write_to_with_cached_sizes
0.1% 0.2% 6.9KiB protobuf <protobuf::descriptor::FileDescriptorProto as protobuf::core::Message>::merge_from
It would be useful to sum all protobuf::core::Message::merge_from
functions and find next largest generic bloated function.
Currenly cargo bloat
supports filtering by crate.
I might be helpful to:
# cargo bloat --filter-re 'FieldDescriptorProto`
Find all symbols containing substring FieldDescriptorProto
, display top 20 of them, display size sum of all symbols, and total size as usual.
I have a large project with a [workspace]
at the root, and several subcrates. I'd like to run cargo bloat on only one of those subcrates, but even if I run cargo bloat in the subdirectory of one of the crates, it looks as though it still parses the entire workspace (that is, all the crates). For example, if I run cargo bloat
in basics/
, I still get an error because of an unsupported Cargo feature (#20) in benchmarks/Cargo.toml
. The --filter
flag does not seem to help here either (I'm guessing it just does grepping after the fact).
The ability to only scan one crate is not only useful, but also nearly essential for very large projects. Running analysis over the whole workspace would be pretty expensive, especially if you only "care" about one subcrate.
It only prints "No binaries are built."
This seems different from #5
running ./target/debug/cargo-bloat
terminates with Error: qwe.
./target/debug/cargo-bloat bloat
works however. (can we suggest that instead printing "qwe" maybe?)
repo @ 74f1977
The new --time
feature is cool! But it would be helpful if instead of running a full cargo clean
beforehand, it would only remove the relevant directory (e.g. target/debug
). Now my release build and documentation are also gone, and those take a pretty long time to build from scratch on my old and slow laptop.
For example, running cargo bloat
on https://github.com/rust-lang-nursery/rust-clippy/ fails:
error: failed to parse manifest at `/home/matthias/vcs/github/rust-clippy/Cargo.toml`
Caused by:
unknown cargo feature `edition`
Many cargo commands have this flag.
--no-default-features Do not build the `default` feature
It is common to see, for example, Cargo.lock reference two or three versions of env_logger, log, ordermap, rand, etc. The consequence of having multiple versions of crates in the dependency tree is:
In one relatively small project, I found that 10 different libraries were duplicated in our Cargo.lock. (It's too early to report the before/after size difference or built time in the project, since I'm still in the process of fixing this.)
This is the command line I use to find duplicates:
cat Cargo.lock | grep "^ \"" | cut -d " " -f 2,3 | sort | uniq | cut -d " " -f 1 | uniq -c | grep -v " 1"
It always print all the crates.
hello!
the lockfile in the 0.6.3 release tarball is outdated which breaks cargo build --release --locked
. Make sure you run eg. cargo update or cargo check to update Cargo.lock after editing Cargo.toml.
Thanks!
For example the cairo-rs
crate is actually cairo
and I have no idea how to resolve it.
cargo-bloat currently crashes for me on a nostd (embedded) project.
Also NOTE: it's in a workspace
Backtrace:
$ RUST_BACKTRACE=1 cargo-bloat bloat -n 10 --release
Compiling ...
thread 'main' panicked at 'slice index starts at 1461 but ends at 214', src/libcore/slice/mod.rs:2575:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:59
at src/libstd/panicking.rs:197
3: std::panicking::default_hook
at src/libstd/panicking.rs:211
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:474
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:381
6: rust_begin_unwind
at src/libstd/panicking.rs:308
7: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
8: core::slice::slice_index_order_fail
at src/libcore/slice/mod.rs:2575
9: cargo_bloat::parser::parse_null_string
10: cargo_bloat::elf32::parse
11: cargo_bloat::process_crate
12: cargo_bloat::main
13: std::rt::lang_start::{{closure}}
14: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:293
15: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:85
16: std::rt::lang_start_internal
at src/libstd/panicking.rs:272
at src/libstd/panic.rs:394
at src/libstd/rt.rs:48
17: main
18: __libc_start_main
19: _start
Currently cargo bloat
supports only certain executables built by cargo
.
Would be convenient to have an utility not tied to cargo to analyze any rust binary.
because using cargo
directly is not supported.
I just upgraded from 0.5.1 to 0.5.2 as result of a major upgrade frenzy and not cargo bloat
spits out these messages when running for e.g. thumbv6m-none-eabi
:
Processing example blinky
Compiling cortex-m-rt v0.5.3
Compiling cortex-m v0.5.6
Compiling stm32f042 v0.6.1
LLVM ERROR: Global variable '__RESET_VECTOR' has an invalid section specifier '.vector_table.reset_vector': mach-o section specifier requires a segment whose length is between 1 and 16 characters.
error: Could not compile `cortex-m-rt`.
warning: build failed, waiting for other jobs to finish...
error: build failed
Cargo has a recent nightly-only feature for building the Rust standard library (std) as part of a normal build: https://github.com/rust-lang/wg-cargo-std-aware
Consider this example project:
cargo new bloattest
cd bloattest
cat <<'EOF' >> Cargo.toml
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
EOF
cargo build --release --target x86_64-unknown-linux-gnu
cargo-bloat
works properly here:
cargo bloat --release --target x86_64-unknown-linux-gnu
It generates this output:
Finished release [optimized] target(s) in 0.00s
Analyzing target/x86_64-unknown-linux-gnu/release/bloattest
File .text Size Crate Name
2.2% 16.7% 28.7KiB std std::backtrace_rs::symbolize::gimli::elf::<impl std::backtrace_rs::symbolize::gimli::Mapping>::new
0.8% 6.2% 10.7KiB std addr2line::ResUnit<R>::parse_lines
0.7% 5.3% 9.2KiB std miniz_oxide::inflate::core::decompress
0.6% 4.8% 8.3KiB std std::sys_common::backtrace::_print_fmt::{{closure}}
0.4% 2.8% 4.9KiB std addr2line::ResUnit<R>::parse_functions
0.4% 2.8% 4.8KiB std gimli::read::unit::parse_attribute
0.3% 2.4% 4.1KiB std rustc_demangle::v0::Printer::print_type
0.3% 2.3% 3.9KiB std addr2line::Function<R>::parse_children
0.3% 2.2% 3.7KiB std <std::backtrace_rs::symbolize::SymbolName as core::fmt::Display>::fmt
0.3% 2.1% 3.6KiB std gimli::read::rnglists::RngListIter<R>::next
0.3% 1.9% 3.2KiB std core::slice::sort::recurse
0.2% 1.8% 3.1KiB std rustc_demangle::try_demangle
0.2% 1.7% 2.9KiB [Unknown] main
0.2% 1.3% 2.3KiB std gimli::read::line::parse_attribute
0.2% 1.3% 2.2KiB std std::sys_common::backtrace::output_filename
0.2% 1.2% 2.2KiB std core::str::pattern::StrSearcher::new
0.2% 1.2% 2.1KiB std rustc_demangle::v0::Printer::print_path
0.1% 1.1% 1.9KiB std gimli::read::unit::Attribute<R>::value
0.1% 1.0% 1.7KiB std std::backtrace_rs::symbolize::gimli::callback
0.1% 0.9% 1.6KiB std std::backtrace_rs::print::BacktraceFrameFmt::print_raw
5.0% 37.8% 65.0KiB And 228 smaller methods. Use -n N to show more.
13.4% 100.0% 172.1KiB .text section size, the file size is 1.3MiB
Cargo's new build-std
feature can reduce the executable size:
rustup component add rust-src
cargo build --release \
--target x86_64-unknown-linux-gnu \
-Z build-std=panic_abort,std \
-Z build-std-features=panic_immediate_abort
cargo-bloat
doesn't work with this build method:
cargo bloat --release \
--target x86_64-unknown-linux-gnu \
-Z build-std=panic_abort,std \
-Z build-std-features=panic_immediate_abort
The above results in this error:
Error: unused arguments left: -Z, build-std=panic_abort,std, -Z, build-std-features=panic_immediate_abort.
If cargo-bloat
would pass along the various nightly-only -Z
arguments to cargo build
, it could be used successfully. As a proof-of-concept, here is a cargo
shim to force the build-std
arguments:
mkdir cargo-bin
cat <<'EOF' > cargo-bin/cargo
#!/bin/sh
if [ "$1" = "build" ]; then
shift
set -- build \
-Z build-std=panic_abort,std \
-Z build-std-features=panic_immediate_abort \
"$@"
fi
exec ~/.rustup/toolchains/nightly-2020-08-20-x86_64-unknown-linux-gnu/bin/cargo "$@"
EOF
chmod +x cargo-bin/cargo
The shim assumes the toolchain "nightly-2020-08-20" for convenience. Now cargo-bloat
works properly:
PATH="$PWD/cargo-bin:$PATH" cargo bloat --release \
--target x86_64-unknown-linux-gnu
It generates this output:
Finished release [optimized] target(s) in 0.06s
Analyzing target/x86_64-unknown-linux-gnu/release/bloattest
File .text Size Crate Name
3.1% 9.6% 1.4KiB [Unknown] main
2.5% 7.9% 1.1KiB core <str as core::fmt::Debug>::fmt
1.4% 4.3% 631B std? <std::io::Write::write_fmt::Adaptor<T> as core::fmt::Write>::write_str
1.4% 4.3% 624B std std::thread::Thread::new
1.3% 4.2% 609B std std::io::stdio::stdout
1.3% 3.9% 567B bloattest bloattest::main
1.2% 3.8% 554B core core::fmt::Formatter::pad_integral
1.1% 3.3% 478B std std::sync::once::Once::call_once::{{closure}}
1.0% 3.1% 454B core core::fmt::write
0.7% 2.2% 319B std std::sys::unix::thread_local_dtor::register_dtor
0.7% 2.2% 315B std std::io::buffered::BufWriter<W>::flush_buf
0.6% 2.0% 290B std std::sys::unix::stack_overflow::imp::signal_handler
0.6% 1.9% 282B core core::fmt::Formatter::pad
0.5% 1.5% 216B core core::unicode::printable::check
0.4% 1.4% 199B std? <std::io::Write::write_fmt::Adaptor<T> as core::fmt::Write>::write_str
0.4% 1.3% 196B std <std::io::buffered::BufWriter<W> as std::io::Write>::write
0.4% 1.3% 192B core core::fmt::num::imp::fmt_u64
0.4% 1.2% 182B core core::str::slice_error_fail
0.4% 1.2% 178B std std::sys_common::thread_info::THREAD_INFO::__getit
0.4% 1.2% 173B std <std::io::stdio::Stdout as std::io::Write>::write_fmt
11.7% 36.4% 5.2KiB And 113 smaller methods. Use -n N to show more.
32.3% 100.0% 14.2KiB .text section size, the file size is 44.1KiB
Would it be possible to add support for Cargo's build-std
feature to cargo-bloat
?
If, for example, you have a Cargo.toml like this:
[features]
default = []
source = ["syn", "quote"]
[[bin]]
name = "main_bin"
[[bin]]
name = "another_bin"
required-features = ["source"]
If you only want to see the output for main_bin
, there's no way to do this. In addition, you must specify --features source
for cargo bloat
to even start.
% cargo bloat --release --crates -n 0
error: target `another_bin` requires the features: `source`
Consider enabling them by passing e.g. `--features="source"`
It appears like goblin has support for PE files, so could windows support be added?
I'm currently working on a project that requires very basic parsing of ELF, Mach-O and PE formats - essentially enumerating sections and extracting the data from a section with a specific name. libgoblin
seems to be an overkill for this task, and I'd like to avoid unsafe code, so the parsers in cargo-bloat seem to fit the bill nicely.
Would you be interested in splitting the parsers into a shared crate? I'll harden the crate against untrusted input (panics, OOMs, etc), but that is probably not a concern for cargo-bloat. Perhaps wider testing of the shared code would be beneficial.
repo @ 74f1977
RUST_BACKTRACE=Full RUSTC_WRAPPER="" ./target/debug/cargo-bloat bloat
Compiling ...
thread 'main' panicked at 'slice index starts at 102607 but ends at 496', src/libcore/slice/mod.rs:2561:5
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.29/src/backtrace/libunwind.rs:88
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.29/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:47
3: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:36
4: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:200
5: std::panicking::default_hook
at src/libstd/panicking.rs:214
6: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:477
7: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:384
8: rust_begin_unwind
at src/libstd/panicking.rs:311
9: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
10: core::slice::slice_index_order_fail
at src/libcore/slice/mod.rs:2561
11: <core::ops::range::Range<usize> as core::slice::SliceIndex<[T]>>::index
at /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libcore/slice/mod.rs:2730
12: <core::ops::range::RangeFrom<usize> as core::slice::SliceIndex<[T]>>::index
at /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libcore/slice/mod.rs:2813
13: core::slice::<impl core::ops::index::Index<I> for [T]>::index
at /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libcore/slice/mod.rs:2538
14: cargo_bloat::parser::parse_null_string
at src/parser.rs:158
15: cargo_bloat::elf64::parse_symbols
at src/elf64.rs:112
16: cargo_bloat::elf64::parse_section_header
at src/elf64.rs:82
17: cargo_bloat::elf64::parse
at src/elf64.rs:34
18: cargo_bloat::collect_self_data
at src/main.rs:735
19: cargo_bloat::process_crate
at src/main.rs:594
20: cargo_bloat::main
at src/main.rs:173
21: std::rt::lang_start::{{closure}}
at /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/rt.rs:64
22: std::rt::lang_start_internal::{{closure}}
at src/libstd/rt.rs:49
23: std::panicking::try::do_call
at src/libstd/panicking.rs:296
24: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:82
25: std::panicking::try
at src/libstd/panicking.rs:275
26: std::panic::catch_unwind
at src/libstd/panic.rs:394
27: std::rt::lang_start_internal
at src/libstd/rt.rs:48
28: std::rt::lang_start
at /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/rt.rs:64
29: main
30: __libc_start_main
31: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
I'd love to leverage the output of cargo-bloat in a development dashboard.
For this a json
output format would be greatly appreciated.
Problem
If cargo bloat
is run outside of a project directory, cargo reports that it can't execute itself because it's not in the PATH.
Steps
:~$ cargo bloat
Compiling ...
Error: failed to execute 'cargo'. It should be in the PATH.
Possible Solution(s)
Probably the same output should be shown as if cargo run
were executed outside a project directory:
~$ cargo run
error: could not find `Cargo.toml` in `/home/andy` or any parent directory
Notes
This is a minor bug I found when someone suggested I run cargo bloat
before I had reached section 1.3 of the book. I didn't understand that cargo
really only has an effect when working with projects created with cargo new
.
Output of cargo version
: cargo 1.30.0 (36d96825d 2018-10-24)
OS platform: Debian Linux 9
I just tried the tool out but I do come across odd behavior. According to all examples inside the readme file, this should work: cargo bloat --release -n 10
. But I get this output instead:
me@tokyo:/p/projects/rust/git-cm$ cargo bloat --release -n 10
Finished release [optimized] target(s) in 0.12s
Analyzing target/release/git-cm
File .text Size Crate Name
0.0% NaN% 0B And 0 smaller methods. Use -n N to show more.
0.0% 100.0% 0B .text section size, the file size is 1.7MiB
how to reproduce, with the example of a fresh git checkout:
cd tmp && git clone https://github.com/eqrion/cbindgen.git
cd cbindgen
cargo bloat
compiling...
Error: failed to find a dir with std libraries. Expected location: /usr/lib/rustlib/x86_64-unknown-linux-gnu/lib.
this is on a x86_64 machine, hence there's /usr/lib64/${RUSTVERSION}/ where rustlib resides. Not sure wether that is excentric behavior from my distro? :-)
cargo-bloat only returns the size of the text-section of the binary. It would be more useful to try to figure out the size of a library in the whole binary (or to make it more explicit that it only deals with the text section somehow).
Also, would it be possible to include per-library how big the debug symbols for a particular library are?
$ rustc --version && rustup --version && cargo --version
rustc 1.36.0-nightly (7158ed9cb 2019-05-15)
rustup 1.18.2 (a0bf3c9cb 2019-05-02)
cargo 1.36.0-nightly (759b6161a 2019-05-06)
Fails:
$ cargo install cargo-bloat --features regex-filter
Updating crates.io index
Installing cargo-bloat v0.8.0
Compiling memchr v2.2.1
Compiling libc v0.2.60
Compiling lazy_static v1.3.0
Compiling ucd-util v0.1.5
Compiling utf8-ranges v1.0.3
Compiling rustc-demangle v0.1.15
Compiling json v0.11.14
Compiling pico-args v0.1.0
Compiling multimap v0.5.0
error[E0277]: the trait bound `std::string::String: std::convert::From<&std::string::String>` is not satisfied
--> /Users/mbana/.cargo/registry/src/github.com-1ecc6299db9ec823/pico-args-0.1.0/src/lib.rs:267:18
|
267 | .map(String::from)
| ^^^^^^^^^^^^ the trait `std::convert::From<&std::string::String>` is not implemented for `std::string::String`
|
= help: the following implementations were found:
<std::string::String as std::convert::From<&str>>
<std::string::String as std::convert::From<std::borrow::Cow<'a, str>>>
<std::string::String as std::convert::From<std::boxed::Box<str>>>
= note: required by `std::convert::From::from`
error[E0277]: the trait bound `std::string::String: std::convert::From<&std::string::String>` is not satisfied
--> /Users/mbana/.cargo/registry/src/github.com-1ecc6299db9ec823/pico-args-0.1.0/src/lib.rs:265:39
|
265 | let flags_left: Vec<String> = self.0.iter()
| _______________________________________^
266 | | .filter(|s| *s != "-" && s.starts_with('-'))
267 | | .map(String::from)
| |______________________________^ the trait `std::convert::From<&std::string::String>` is not implemented for `std::string::String`
|
= help: the following implementations were found:
<std::string::String as std::convert::From<&str>>
<std::string::String as std::convert::From<std::borrow::Cow<'a, str>>>
<std::string::String as std::convert::From<std::boxed::Box<str>>>
= note: required by `std::convert::From::from`
error[E0277]: the trait bound `std::string::String: std::convert::From<&std::string::String>` is not satisfied
--> /Users/mbana/.cargo/registry/src/github.com-1ecc6299db9ec823/pico-args-0.1.0/src/lib.rs:265:39
|
265 | let flags_left: Vec<String> = self.0.iter()
| _______________________________________^
266 | | .filter(|s| *s != "-" && s.starts_with('-'))
267 | | .map(String::from)
268 | | .collect();
| |______________________^ the trait `std::convert::From<&std::string::String>` is not implemented for `std::string::String`
|
= help: the following implementations were found:
<std::string::String as std::convert::From<&str>>
<std::string::String as std::convert::From<std::borrow::Cow<'a, str>>>
<std::string::String as std::convert::From<std::boxed::Box<str>>>
= note: required by `std::convert::From::from`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
error: Could not compile `pico-args`.
warning: build failed, waiting for other jobs to finish...
error: failed to compile `cargo-bloat v0.8.0`, intermediate artifacts can be found at `/var/folders/kv/g0dcmzwx6kj367r3vgqmwk2m0000gp/T/cargo-installSqQucc`
Caused by:
build failed
Works:
NB: I cannot use --features regex-filter
because it looks like this was just added recently.
$ cargo install cargo-bloat --version=0.7.2
Updating crates.io index
Installing cargo-bloat v0.7.2
Downloaded goblin v0.0.19
Downloaded object v0.11.0
Downloaded syn v0.15.40
Downloaded plain v0.2.3
Downloaded scroll v0.9.2
Downloaded scroll_derive v0.9.5
Compiling proc-macro2 v0.4.30
Compiling semver-parser v0.7.0
Compiling unicode-xid v0.1.0
Compiling syn v0.15.40
Compiling cc v1.0.37
Compiling libc v0.2.60
Compiling log v0.4.7
Compiling memchr v2.2.1
Compiling crc32fast v1.2.0
Compiling bitflags v1.1.0
Compiling serde v1.0.97
Compiling cfg-if v0.1.9
Compiling unicode-width v0.1.5
Compiling unicode-segmentation v1.3.0
Compiling ryu v1.0.0
Compiling plain v0.2.3
Compiling lazy_static v1.3.0
Compiling ucd-util v0.1.5
Compiling vec_map v0.8.1
Compiling ansi_term v0.11.0
Compiling strsim v0.8.0
Compiling utf8-ranges v1.0.3
Compiling uuid v0.7.4
Compiling itoa v0.4.4
Compiling rustc-demangle v0.1.15
Compiling semver v0.9.0
Compiling textwrap v0.11.0
Compiling thread_local v0.3.6
Compiling regex-syntax v0.6.10
Compiling heck v0.3.1
Compiling rustc_version v0.2.3
Compiling atty v0.2.13
Compiling time v0.1.42
Compiling term_size v0.3.1
Compiling memmap v0.7.0
Compiling aho-corasick v0.7.4
Compiling clap v2.33.0
Compiling scroll v0.9.2
Compiling miniz-sys v0.1.12
Compiling quote v0.6.13
Compiling flate2 v1.0.9
Compiling regex v1.2.0
Compiling serde_json v1.0.40
Compiling multimap v0.5.0
Compiling scroll_derive v0.9.5
Compiling structopt-derive v0.2.18
Compiling serde_derive v1.0.97
Compiling structopt v0.2.18
Compiling goblin v0.0.19
Compiling object v0.11.0
Compiling cargo-bloat v0.7.2
Finished release [optimized] target(s) in 1m 06s
Installing /Users/mbana/.cargo/bin/cargo-bloat
Installed package `cargo-bloat v0.7.2` (executable `cargo-bloat`)
Interesting crate! In contrast to what the Readme assumes, it doesn't work on macOS. Curiously, it doesn't really fail, but instead outputs this (for cargo-edit):
NaN% 0B [10222 Others]
NaN% 0B _je_tcache_boot
NaN% 0B _je_tcache_cleanup
NaN% 0B _je_tcache_create
NaN% 0B _je_tcache_enabled_cleanup
NaN% 0B _je_tcache_event_hard
NaN% 0B _je_tcache_get_hard
NaN% 0B _je_tcache_stats_merge
NaN% 0B _je_tcaches_create
NaN% 0B _je_tcaches_destroy
NaN% 0B _je_tcaches_flush
NaN% 0B _je_thread_allocated_cleanup
NaN% 0B _je_thread_deallocated_cleanup
NaN% 0B _je_tsd_cleanup
NaN% 0B _je_tsd_init_check_recursion
NaN% 0B _je_tsd_init_finish
NaN% 0B _je_witness_fork_cleanup
NaN% 0B _je_witnesses_cleanup
NaN% 0B _main
NaN% 0B _rust_begin_unwind
NaN% 0B _rust_eh_personality
100.0% 0B Total
Looks like the object crate just reports 0 bytes all the time? Should it ever return 0?
Using the new mangling scheme is convenient because it gives more information about the particular monomorphization. However it seems like crate detection is broken.
RUSTFLAGS="-Z symbol-mangling-version=v0" rustup run nightly cargo bloat --release
gives
0.0% 0.7% 61.2KiB [Unknown] <gleam[d1379dfb6ebdd7c7]::ffi_gl::Gl>::load_with::<wrench[a4e3b033c434546e]::make_window::{closure#0}
0.0% 0.7% 61.1KiB [Unknown] <gleam[d1379dfb6ebdd7c7]::ffi_gl::Gl>::load_with::<wrench[a4e3b033c434546e]::make_window
0.0% 0.6% 52.5KiB [Unknown] <wrench[a4e3b033c434546e]::yaml_frame_writer::YamlFrameWriter>
0.0% 0.6% 47.6KiB regex_syntax <regex_syntax[f84e6df1bfbac060]::ast::parse::ParserI<&mut regex_syntax[f84e6df1bfbac060]::ast::parse::Parser>>
0.0% 0.5% 40.2KiB [Unknown] <webrender[58737326ba1c09f4]::display_list_flattener::DisplayListFlattener>
0.0% 0.5% 37.5KiB [Unknown] <wrench[a4e3b033c434546e]::rawtest::RawtestHarness>
0.0% 0.5% 37.3KiB [Unknown] <wrench[a4e3b033c434546e]::yaml_frame_reader::YamlFrameReader>
0.0% 0.4% 35.1KiB [Unknown] wrench[a4e3b033c434546e]
0.0% 0.4% 34.7KiB [Unknown] <webrender[58737326ba1c09f4]::render_backend::RenderBackend>
0.0% 0.4% 33.7KiB webrender <webrender[58737326ba1c09f4]::renderer::Renderer>
Cargo recently got support for renaming dependencies. That is, you can do:
cargo-features = ["rename-dependency"]
# ...
[dependencies]
bar = { version = "0.1", package = "foo" }
To import the crate foo
under the name bar
. However, this seems to confuse cargo-bloat
, which reports:
error: failed to parse manifest at `/home/jon/dev/projects/distributary/benchmarks/Cargo.toml`
Caused by:
unknown cargo feature `rename-dependency`
Thanks for this awesome tool! I'm building a github action to run cargo bloat
on projects. Would you be willing to add support for distributing pre-built binaries via github releases, for environments where a cargo install
would be too slow or expensive?
This can be entirely automated with Github actions themselves.
Thanks for creating this tool! ๐
Is there a way to run cargo bloat on crates that are just libraries? If you need an executable to run on, I could pass --example foo
to generate an executable for that particular example. I would like to use this on my crates to see if any functions/dependencies are taking up most of the binary generated by anyone using the crate.
I think 5c535f4 broke cargo-bloat on macs. Every commit with this and afterwards doesn't output anything:
% git checkout 5c535f450eb94491c1ed72ccbe0d4368cd916523
% cargo run bloat --crates -n 2
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
Running `target/debug/cargo-bloat bloat --crates -n 2`
Compiling ...
Analyzing target/debug/cargo-bloat
File .text Size Name
0.0% 100.0% 0B .text section size, the file size is 13.0MiB
Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
Everything before that seems to work:
% git checkout e429559df8d1641886e41d617c68b8db43d6fc9b
% cargo run bloat --crates -n 2
...
Running `target/debug/cargo-bloat bloat --crates -n 2`
Compiling ...
Analyzing target/debug/cargo-bloat
File .text Size Name
12.8% 31.1% 1.6MiB std
8.2% 19.9% 1016.7KiB clap
41.3% 100.0% 5.0MiB .text section size, the file size is 12.1MiB
Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
Add support for comparing two versions of the same crate. Presumably previous with the current.
Current problems:
The generic function like this:
use std::fmt;
fn main() {
method_t(5);
method_t(5.5);
}
fn method_t<T: fmt::Debug>(v: T) {
println!("{:?}", v);
}
will be mangled to:
test_crate::method_t::h6162eaf340852a5e
test_crate::method_t::h28b0347ca3fd97b7
which is not enough to distinct them.
See the diff_flag
branch for details.
Current result for a very simple case:
T Diff After Before Name
~ -356B 153B 509B diff_1::method_2::hc8b4ee49810e32f4
+ +168B 168B 0B diff_1::method_t::h6162eaf340852a5e
+ +153B 153B 0B diff_1::method_3::hc5483bc7235c0d34
- -153B 0B 153B diff_1::method_4::hd871316cadbf27f6
+ +59B 59B 0B core::fmt::float::<impl core::fmt::Debug for f64>::fmt::h3cb1f30de74245fd
- -54B 0B 54B <&'a T as core::fmt::Debug>::fmt::hb9afa5b4b803de51
~ -5B 166B 171B diff_1::method_t::h28b0347ca3fd97b7
~ +4B 44B 40B diff_1::main::h07ba656a65889591
-184B - - Total
I follow the readme file to use the cargo bloat.However the result does not seems like the sample result in readme file .
This is my cmd and result:
$ cargo bloat --release --crates
Compiling ...
Analyzing target/release/libtest.dylib
File .text Size Name
0.0% 100.0% 0B .text section size, the file size is 26.4MiB
Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
Cargo Bloat Version:
0.8.1
Rustc Version:
rustc 1.38.0-nightly (83e4eed16 2019-07-14)
Possibly tangentially related to #21, though I'm not sure.
When I am running cargo bloat on my project, it tells me that it only supports bin
or cdylib
targets. This is fine. However, the proper way to build my binary is cargo build --package sarcasm --bin sarcasm
. There doesn't appear to be a proper way to pass through that information to cargo bloat so it invokes the proper build command.
I don't know how cargo bloat detects if there is a generated binary/where it is, but it may be possible to just add support for passing that flag through directly.
If you need any more information, feel free to ask ๐
Thanks for making this tool.
It's not uncommon for large rust symbols to have a lot inlined into them. It would be nice to be able to see a histogram of how much each inlined symbol is contributing to large actual symbol.
The addr2line crate supports producing inline call stacks for a particular address.
From my comment on reddit. Even though it was quickly solved, I can't imagine I'll be the only one tripped up by this.
I ran $ cargo bloat --release --crates
expecting to see all the crates but only got the top 20. It took me a while until I realized I needed to pass something like $ cargo bloat --release -n 999 --crates
to see eerything.
Adding --all
for "all lines" or simply removing the default of 20 would be good IMO. Personally I prefer just removing the default of 20 since people can cut down the number of lines with -n
or tools like head
just fine. If you'd prefer to add --all
, I think it'd be good practice to output a line saying, "Only outputting top 20 lines, use --all to see everything"
when no -n
is used.
Seeing this error when running cargo-bloat on a project that uses https://github.com/oschwald/maxminddb-rust which seems to generate a .so in addition to the normal static library https://github.com/oschwald/maxminddb-rust/blob/ff8ff2106a867f05d3526b2e9d0f729082ce5745/Cargo.toml#L17.
From m4b/goblin#113 it appears that cargo-bloat treats the .so as an archive.
Error: 'goblin' failed to parse '"<SNIP>/target/debug/deps/libmaxminddb-00b74459be63a99f.so"' cause 'Invalid magic number: 0x10102464c457f'.
cargo install cargo-bloat
fails on Windows with the following error message:
error[E0425]: cannot find function collect_self_data
in this scope
--> src\main.rs:594:23
|
594 | data: collect_self_data(&artifact.path)?,
| ^^^^^^^^^^^^^^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try rustc --explain E0425
.
error: Could not compile cargo-bloat
.
The same error occurs if I clone the repo and attempt to cargo build
there.
It looks like this is because collect_self_data
is cfg'ed to only be defined when compiling on non-OSX Unix targets.
I'm using cargo-bloat
for embedded Cortex-M development which worked fine as until just recently.
I narrowed it down via bisection for convenience but lack the bandwidth to figure out which change exactly caused the break.
So here it still works:
# rustup override set nightly-2018-03-17
info: syncing channel updates for 'nightly-2018-03-17-x86_64-apple-darwin'
275.8 KiB / 275.8 KiB (100 %) 213.1 KiB/s ETA: 0 s
info: latest update on 2018-03-17, rust version 1.26.0-nightly (55c984ee5 2018-03-16)
...
# xargo bloat -v --release --example i2c_haldriver_printmagserial
+ "rustc" "--print" "sysroot"
+ "rustc" "--print" "target-list"
+ RUSTFLAGS="-C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked"
+ "cargo" "build" "--release" "--manifest-path" "/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.XrEVaZ2BK7pg/Cargo.toml" "--target" "thumbv6m-none-eabi" "-v" "-p" "core"
Compiling core v0.0.0 (file:///Users/egger/.rustup/toolchains/nightly-2018-03-17-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore)
Running `rustc --crate-name core /Users/egger/.rustup/toolchains/nightly-2018-03-17-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/lib.rs --crate-type lib --emit=dep-info,link -C opt-level=s -C debuginfo=2 -C metadata=cec4ddb362f84e20 -C extra-filename=-cec4ddb362f84e20 --out-dir /var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.XrEVaZ2BK7pg/target/thumbv6m-none-eabi/release/deps --target thumbv6m-none-eabi -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.XrEVaZ2BK7pg/target/thumbv6m-none-eabi/release/deps -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.XrEVaZ2BK7pg/target/release/deps -C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked`
Finished release [optimized + debuginfo] target(s) in 19.26 secs
...
Finished release [optimized + debuginfo] target(s) in 19.64 secs
File .text Size Name
0.1% 9.2% 392B [43 Others]
0.2% 17.1% 728B core::fmt::Formatter::pad_integral
0.1% 9.4% 400B main
0.1% 8.8% 376B core::fmt::write
0.1% 7.0% 296B GPIOTE
0.1% 6.2% 264B core::fmt::num::<impl core::fmt::Display for i16>::fmt
0.1% 5.7% 244B core::fmt::num::<impl core::fmt::Display for usize>::fmt
0.1% 5.6% 236B compiler_builtins::int::udiv::__udivsi3
0.1% 5.0% 212B <nrf51_hal::i2c::I2c<nrf51::TWI1> as embedded_hal::blocking::i2c::WriteRead>::write_read
0.1% 4.8% 202B core::fmt::Formatter::pad_integral::{{closure}}
0.0% 3.5% 148B <core::fmt::Write::write_fmt::Adapter<'a, T> as core::fmt::Write>::write_char
0.0% 3.2% 136B <mag3110::Mag3110<I2C>>::set_sampling_mode
0.0% 3.0% 128B core::fmt::num::<impl core::fmt::Display for i8>::fmt
0.0% 2.4% 104B <nrf51_hal::i2c::I2c<nrf51::TWI1> as embedded_hal::blocking::i2c::Write>::write
0.0% 2.4% 100B core::fmt::Formatter::getcount
0.0% 1.6% 66B <mag3110::Mag3110<I2C>>::mag
0.0% 1.5% 64B cortex_m_rt::reset_handler
0.0% 1.3% 56B <nrf51_hal::i2c::I2c<nrf51::TWI1>>::recv_byte
0.0% 1.0% 44B <nrf51_hal::serial::Tx<UART> as core::fmt::Write>::write_str
0.0% 0.9% 40B <core::fmt::Write::write_fmt::Adapter<'a, T> as core::fmt::Write>::write_fmt
0.0% 0.3% 14B <core::fmt::Write::write_fmt::Adapter<'a, T> as core::fmt::Write>::write_str
1.4% 100.0% 4.2KiB .text section size, the file size is 301.3KiB
While here it doesn't anymore:
# rustup override set nightly-2018-03-19
info: syncing channel updates for 'nightly-2018-03-19-x86_64-apple-darwin'
275.8 KiB / 275.8 KiB (100 %) 183.6 KiB/s ETA: 0 s
info: latest update on 2018-03-19, rust version 1.26.0-nightly (5508b2714 2018-03-18)
...
# xargo bloat -v --release --example i2c_haldriver_printmagserial
+ "rustc" "--print" "sysroot"
+ "rustc" "--print" "target-list"
+ RUSTFLAGS="-C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked"
+ "cargo" "build" "--release" "--manifest-path" "/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.I1pstNt43TDG/Cargo.toml" "--target" "thumbv6m-none-eabi" "-v" "-p" "core"
Compiling core v0.0.0 (file:///Users/egger/.rustup/toolchains/nightly-2018-03-19-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore)
Running `rustc --crate-name core /Users/egger/.rustup/toolchains/nightly-2018-03-19-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/lib.rs --crate-type lib --emit=dep-info,link -C opt-level=s -C debuginfo=2 -C metadata=679b0e558e3e4047 -C extra-filename=-679b0e558e3e4047 --out-dir /var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.I1pstNt43TDG/target/thumbv6m-none-eabi/release/deps --target thumbv6m-none-eabi -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.I1pstNt43TDG/target/thumbv6m-none-eabi/release/deps -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.I1pstNt43TDG/target/release/deps -C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked`
Finished release [optimized + debuginfo] target(s) in 19.7 secs
+ RUSTFLAGS="-C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked"
+ "cargo" "build" "--release" "--manifest-path" "/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/Cargo.toml" "--target" "thumbv6m-none-eabi" "-v" "-p" "compiler_builtins"
Compiling compiler_builtins v0.1.0 (file:///Users/egger/.rustup/toolchains/nightly-2018-03-19-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcompiler_builtins)
Running `rustc --crate-name build_script_build /Users/egger/.rustup/toolchains/nightly-2018-03-19-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcompiler_builtins/build.rs --crate-type bin --emit=dep-info,link -C opt-level=s -C debuginfo=2 --cfg 'feature="compiler-builtins"' --cfg 'feature="default"' --cfg 'feature="mem"' -C metadata=67f0d7aa4cf8ccaf -C extra-filename=-67f0d7aa4cf8ccaf --out-dir /var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/release/build/compiler_builtins-67f0d7aa4cf8ccaf -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/release/deps`
Running `/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/release/build/compiler_builtins-67f0d7aa4cf8ccaf/build-script-build`
Running `rustc --crate-name compiler_builtins /Users/egger/.rustup/toolchains/nightly-2018-03-19-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcompiler_builtins/src/lib.rs --crate-type lib --emit=dep-info,link -C opt-level=s -C debuginfo=2 --cfg 'feature="compiler-builtins"' --cfg 'feature="default"' --cfg 'feature="mem"' -C metadata=d959421ece4be114 -C extra-filename=-d959421ece4be114 --out-dir /var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/thumbv6m-none-eabi/release/deps --target thumbv6m-none-eabi -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/thumbv6m-none-eabi/release/deps -L dependency=/var/folders/8f/ch8vbtq93ldfc4vksdp5cw540000gn/T/xargo.kAqwf8xbqrAu/target/release/deps -C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo -Z force-unstable-if-unmarked --cfg thumb --cfg thumbv6m`
Finished release [optimized + debuginfo] target(s) in 2.47 secs
+ RUSTFLAGS="-C link-arg=-Tlink.x -C linker=arm-none-eabi-ld -Z linker-flavor=ld --sysroot /Users/egger/.xargo"
+ "cargo" "bloat" "-v" "--release" "--example" "i2c_haldriver_printmagserial"
error: Invalid arguments.
Usage: cargo bloat [options]
Not sure how realistic that is, but for wasm builds size matters a lot, so having cargo bloat support it would be fantastic.
When run on crates.io, this is the output:
[master][~/builds/crates.io] cargo bloat --bin server --release
Compiling ...
Analyzing target/release/server
File .text Size Crate Name
51.0% 88.8% 6.9MiB [21655 Others]
1.0% 1.8% 143.4KiB html5ever <html5ever::tree_builder::TreeBuilder<Handle, Sink>>::step
0.9% 1.5% 123.4KiB unicode_normalization unicode_normalization::tables::compatibility_fully_decomposed
0.5% 0.9% 71.8KiB unicode_normalization unicode_normalization::tables::canonical_fully_decomposed
0.4% 0.7% 52.5KiB jemalloc_sys __rjem_je_prof_backtrace
0.4% 0.6% 51.7KiB regex <regex::exec::ExecNoSync<'c> as regex::re_trait::RegularExpression>::read_captures_at
0.4% 0.6% 50.8KiB unicode_normalization unicode_normalization::tables::is_combining_mark
0.3% 0.6% 46.5KiB regex_syntax <regex_syntax::ast::parse::ParserI<'s, P>>::parse_with_comments
0.3% 0.6% 46.2KiB regex <regex::exec::ExecNoSync<'c> as regex::re_trait::RegularExpression>::read_captures_at
0.3% 0.5% 39.8KiB comrak? <comrak::scanners::Lexer as pest::parser::Parser<comrak::scanners::Rule>>::parse::{{closure}}
0.2% 0.4% 33.6KiB unicode_normalization unicode_normalization::tables::composition_table
0.2% 0.4% 31.7KiB html5ever <html5ever::tokenizer::Tokenizer<Sink>>::step
0.2% 0.3% 27.2KiB regex_syntax regex_syntax::parser::Parser::parse_expr
0.2% 0.3% 26.0KiB idna core::iter::iterator::Iterator::ne
0.2% 0.3% 25.7KiB std? <alloc::string::String as core::iter::traits::Extend<char>>::extend
0.2% 0.3% 24.7KiB unicode_normalization <unicode_normalization::decompose::Decompositions<I>>::push_back
0.2% 0.3% 22.8KiB [Unknown] _stats_arena_print
0.2% 0.3% 21.4KiB http http::header::name::parse_hdr
0.2% 0.3% 20.9KiB serde_json? <&'a mut serde_json::de::Deserializer<R> as serde::de::Deserializer<'de>>::deserialize_struct
0.1% 0.2% 17.9KiB comrak comrak::parser::inlines::Subject::parse_inline
0.1% 0.2% 17.5KiB jemalloc_sys __rjem_rallocx
57.5% 100.0% 7.8MiB .text section size, the file size is 13.6MiB
To me, this output implies that it just showed me the 20 smallest functions, and that there are 21655 other items which are larger than the second line in the list, and were not shown. I assume that's not actually what's going on, and there are in fact 21655 items smaller than 17.5KiB which were not shown.
To me, it'd make more sense to display that item directly above the .text
item, and perhaps even make things extra clear by changing [21655 others]
to [21655 items smaller than {size of smallest shown item} not shown]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.