dtolnay / cargo-llvm-lines Goto Github PK
View Code? Open in Web Editor NEWCount lines of LLVM IR per generic function
License: Apache License 2.0
Count lines of LLVM IR per generic function
License: Apache License 2.0
It would be nice to be able to use cargo llvm-lines
to debug slow test compilation times too, but as far as I can tell it doesn't support counting the lines for cargo test
.
This request is similar to #16 but for the entire test suite rather than an individual test, which might be easier (or harder) to implement.
Basically this. For example the instantiations of HashMap::insert could be:
HashMap<(alloc::string::String, usize), alloc::rc::Rc<core::cell::RefCell<mir::node::MirNode>>>
HashMap<(dataflow::domain::Index, usize), (dataflow::statistics::DomainStats, std::collections::hash::map::HashMap<petgraph::graph_impl::NodeIndex<u32>, dataflow::statistics::NodeStats>)>
HashMap<(dataflow::domain::Index, usize), usize, core::hash::BuildHasherDefault<fnv::FnvHasher>>
HashMap<(petgraph::graph_impl::NodeIndex<u32>, petgraph::graph_impl::NodeIndex<u32>), petgraph::graph_impl::NodeIndex<u32>>
HashMap<alloc::string::String, ()>
HashMap<alloc::string::String, controller::sql::query_graph::QueryGraphNode>
HashMap<alloc::string::String, petgraph::graph_impl::NodeIndex<u32>>
HashMap<alloc::string::String, usize>
HashMap<alloc::vec::Vec<usize>, ()>
HashMap<core::any::TypeId, alloc::boxed::Box<hyper::header::Header>>
HashMap<core::any::TypeId, alloc::boxed::Box<hyper::header::HeaderFormat>>
HashMap<dataflow::domain::Index, ()>
HashMap<dataflow::domain::Index, i64>
HashMap<nom_sql::column::Column, ()>
HashMap<petgraph::graph_impl::NodeIndex<u32>, ()>
HashMap<petgraph::graph_impl::NodeIndex<u32>, (alloc::vec::Vec<usize>, bool)>
HashMap<petgraph::graph_impl::NodeIndex<u32>, alloc::vec::Vec<core::addressing::LocalNodeIndex>>
HashMap<petgraph::graph_impl::NodeIndex<u32>, core::addressing::IndexPair>
HashMap<petgraph::graph_impl::NodeIndex<u32>, dataflow::Sharding>
HashMap<petgraph::graph_impl::NodeIndex<u32>, dataflow::statistics::NodeStats>
HashMap<petgraph::graph_impl::NodeIndex<u32>, usize>
HashMap<u64, (controller::sql::query_graph::QueryGraph, mir::query::MirQuery)>
I am trying to pass arguments to rustc and it is failing with unrecognized options. Example:
cargo llvm-lines -- -q
Compiling time v0.2.25 (/home/blah/code/time-0.2.25)
error: Unrecognized option: 'q'
error: could not compile `time`
This was with cargo-llvm-lines 0.4.10.
Sort by the second column instead of the first.
👋 it looks like the 0.4.27 release was not completed in the sense of the release was not marked as latest release
despite the action run was completed successfully.
relates to Homebrew/homebrew-core#129244
When enabling v0 symbol mangling (e.g.: by setting rustflags = "-Csymbol-mangling-version=v0"
in the [build]
section of the cargo config file), most duplicate copies of a function end up as their own single-copy entry in the output instead of being properly grouped.
Perhaps cargo-llvm-lines
should force the symbol mangling to legacy
to ensure proper behavior for projects that normally use v0?
Running cargo llvm-lines
inside fresh project ends with "file not found" message from OS. At first I thought this package doesn't work on Windows but then I saw that the support was added in #8, but I can't really tell what's wrong or which file it can't find...
Steps to reproduce:
cargo init llvmlinestest
cd llvmlinestest
cargo llvm-lines
Output:
Compiling llvmlinestest v0.1.0 (C:\Users\panstromek\IdeaProjects\llvmlinestest)
Finished dev [unoptimized + debuginfo] target(s) in 0.33s
the system cannot find the file specified. (os error 2)
Steps to reproduce:
cargo llvm-lines
cargo llvm-lines
againExpected results: output similar to that of cargo build
after code changes, then showing updated results for LLVM lines and instantiation count.
Actual result: output similar to that of cargo build
after code changes (so code is indeed recompiled), but the lines and count results are exactly the same as the first time, including the renamed function’s old name.
Work-around: cargo clean && cargo llvm-lines
I am pretty confused by what llvm-lines
is actually measuring. I think @nnethercote raised similar concern on internals some time ago, I just found another pretty confusing instance and I don't really understand what's going on.
I have a crate and it has two targets - one lib
and one bin
. bin
target is simple - it doesn't actually do anything, it only calls main function from a lib
.
use legacy_zebra::src::zebra::main as main_lib;
fn main () {
main_lib();
}
And yet, when I run both targets through llvm-lines
, I get completely different output.
cargo llvm-lines --lib
Lines Copies Function name
----- ------ -------------
54411 (100%) 468 (100%) (TOTAL)
2939 (5.4%) 1 (0.2%) engine::src::end::end_tree_search
2549 (4.7%) 1 (0.2%) engine::src::midgame::tree_search
2238 (4.1%) 1 (0.2%) engine::src::getcoeff::unpack_coeffs
1682 (3.1%) 1 (0.2%) engine::src::thordb::database_search
1622 (3.0%) 1 (0.2%) legacy_zebra::src::zebra::main_0
1594 (2.9%) 1 (0.2%) legacy_zebra::src::zebra::analyze_game
1581 (2.9%) 1 (0.2%) engine::src::game::generic_compute_move
1545 (2.8%) 1 (0.2%) engine::src::end::end_game
1512 (2.8%) 1 (0.2%) engine::src::midgame::root_tree_search
1276 (2.3%) 1 (0.2%) legacy_zebra::src::osfbook::add_new_game
1198 (2.2%) 1 (0.2%) engine::src::zebra::engine_play_game
1108 (2.0%) 1 (0.2%) engine::src::osfbook::get_book_move
1010 (1.9%) 1 (0.2%) legacy_zebra::src::zebra::run_endgame_script
982 (1.8%) 1 (0.2%) legacy_zebra::src::osfbook::book_statistics
927 (1.7%) 1 (0.2%) legacy_zebra::src::osfbook::do_correct
889 (1.6%) 1 (0.2%) engine::src::midgame::middle_game
852 (1.6%) 1 (0.2%) legacy_zebra::src::display::display_board
842 (1.5%) 1 (0.2%) engine::src::getcoeff::load_set
834 (1.5%) 1 (0.2%) engine::src::midgame::fast_tree_search
784 (1.4%) 1 (0.2%) engine::src::thordb::choose_thor_opening_move
722 (1.3%) 1 (0.2%) engine::src::osfbook::fill_move_alternatives
706 (1.3%) 1 (0.2%) legacy_zebra::src::osfbook::convert_opening_list
684 (1.3%) 1 (0.2%) legacy_zebra::src::game::ponder_move
cargo llvm-lines --bin zebra
Lines Copies Function name
----- ------ -------------
163815 (100%) 1340 (100%) (TOTAL)
13340 (8.1%) 1 (0.1%) engine::src::getcoeff::constant_and_parity_feature
4630 (2.8%) 1 (0.1%) std::backtrace_rs::symbolize::gimli::elf::<impl std::backtrace_rs::symbolize::gimli::Mapping>::new
3767 (2.3%) 1 (0.1%) engine::src::doflip::DoFlips_hash
3123 (1.9%) 1 (0.1%) engine::src::getcoeff::terminal_patterns
2800 (1.7%) 1 (0.1%) engine::src::end::end_tree_search
2715 (1.7%) 1 (0.1%) engine::src::doflip::DoFlips_no_hash
2531 (1.5%) 1 (0.1%) addr2line::ResUnit<R>::parse_lines
2471 (1.5%) 1 (0.1%) miniz_oxide::inflate::core::decompress
2426 (1.5%) 1 (0.1%) engine::src::midgame::tree_search
2210 (1.3%) 1 (0.1%) engine::src::getcoeff::unpack_coeffs
2082 (1.3%) 107 (8.0%) core::ptr::drop_in_place
2056 (1.3%) 1 (0.1%) std::backtrace_rs::symbolize::gimli::resolve
1644 (1.0%) 1 (0.1%) gimli::read::unit::parse_attribute
1624 (1.0%) 1 (0.1%) engine::src::thordb::database_search
1490 (0.9%) 1 (0.1%) legacy_zebra::src::zebra::analyze_game
1464 (0.9%) 1 (0.1%) gimli::read::unit::Attribute<R>::value
1440 (0.9%) 1 (0.1%) engine::src::game::generic_compute_move
1440 (0.9%) 1 (0.1%) engine::src::midgame::root_tree_search
1424 (0.9%) 1 (0.1%) engine::src::end::solve_parity_hash_high
1374 (0.8%) 1 (0.1%) engine::src::end::end_game
1308 (0.8%) 1 (0.1%) addr2line::ResUnit<R>::parse_functions
1283 (0.8%) 1 (0.1%) legacy_zebra::src::zebra::main_0
1173 (0.7%) 1 (0.1%) engine::src::zebra::engine_play_game
1163 (0.7%) 1 (0.1%) legacy_zebra::src::osfbook::add_new_game
I thought this could be because the main function calls some generic function in dependencies, so if you don't call it, then those dependencies are not codegened. But the main function is actually present in both outputs (as main_0
) - and more than that, it has different line count.
1283 (0.8%) 1 (0.1%) legacy_zebra::src::zebra::main_0
1622 (3.0%) 1 (0.2%) legacy_zebra::src::zebra::main_0
This is really confusing to me, and I don't really understand how to interpret the results. There's no diference between these targets but the llvm-lines output is massively different and the functions that stand out seems to be all over the place. Some are generic, some are not. Some functions from dependencies are shown, some not (some are generic, some are not).
The project is not open source, yet, so it might be difficult to interpret now. I will open source it in following weeks/months, though.
Hi,
Could a Cargo.lock
file be included in future releases so that downstream Linux packages can be reproducible[1] and, potentially, more reliable?
P.S. Just packaged this for ArchLinux: cargo-llvm-linesAUR.
I'm just giving it a whirl and it seems like it still takes the full compile time to get the pre-LLVM line counts out; is that fundamental somehow? I'm looking at a binary that takes 20mins+ to build in release, and it seems to do a full debug build (352s).
Someone may know the right flags to pass to have the compiler finish as soon as the LLVM IR is written out, rather than producing the full binary as well. If there is not a flag, we can have cargo-llvm-lines kill the compiler process as soon as the IR file has been fully written.
For example cargo llvm-lines help
will spawn tens of cargo rustc help
processes per second and eventually OOM the system.
The alignment is broken when numbers get large.
Echidnatron% time cargo llvm-lines
Compiling tpchlike v0.1.0 (file:///Users/mcsherry/Projects/differential-dataflow/tpchlike)
Finished dev [unoptimized + debuginfo] target(s) in 352.27 secs
1332608 2031 <core::slice::Iter<'a, T>>::search_while
440031 4621 <core::option::Option<T>>::map
419929 21396 core::ptr::drop_in_place
347867 745 alloc::slice::merge_sort
306676 1394 <alloc::raw_vec::RawVec<T, A>>::double
219402 745 alloc::slice::insert_head
208600 745 alloc::slice::merge
(Feature request) An option that would be equivalent to --example X or --test Y, and show the instantiations for that target.
We've been using cargo llvm-lines
with great success (before, after) in rust-analyzer!
One thing we've noticed is that the biggest win comes from noticing things that are monomorphised in the wrong crate. Basically, if you have a generic fn<T> foo()
function in crate A
, and use it in crates B
and C
, you compile it twice. At the moment, cargo llvm-lines
surfaces this info only indirectly, as it works on a crate at a time. So, you can use it to pin-point this issue if you already suspect it might be there, but it's hard to use cargo llvm-lines
to discover it in the first place.
It would be cool (but I totally see how this is a big ask, as cargo llvm-lines
doesn't really work that way :-) ) to be able to apply cargo llvm-lines
to the whole workspace, and see per-crate stats in the same output.
This appears to be a re-occurrence of the issue reported in #4.
To reproduce:
$ git clone https://github.com/pyca/cryptography
$ cd cryptography/src/rust/
$ cargo llvm-lines --version
cargo-llvm-lines 0.4.26
$ cargo llvm-lines --no-default-features --release
Compiling cryptography-rust v0.1.0 (/Users/alex_gaynor/projects/cryptography/src/rust)
warning: ignoring emit path because multiple .ll files were produced
Finished release [optimized] target(s) in 8.28s
Lines Copies Function name
----- ------ -------------
3 1 (TOTAL)
3 (100.0%,100.0%) 1 (100.0%,100.0%) <T as core::convert::Into<U>>::into
It would be nice to have support for passing through cargo's --target
option to get results from a cross-compilation.
Reported here:
$ git clone https://github.com/mit-pdos/distributary
$ cd distributary
$ cargo llvm-lines --manifest-path benchmarks/Cargo.toml --bin vote --release
Compiling benchmarks v0.0.1 (file:///home/jon/dev/projects/distributary/benchmarks)
warning: ignoring emit path because multiple .ll files were produced
Finished release [optimized + debuginfo] target(s) in 9.94 secs
1 1 core::num::dec2flt::algorithm::fpu_precision::set_precision
$ cargo llvm-lines --lib --release
Compiling distributary v0.1.0 (file:///home/jon/dev/projects/distributary)
warning: ignoring emit path because multiple .ll files were produced
Finished release [optimized + debuginfo] target(s) in 90.79 secs
34 1 <serde_json::read::Reference<'b, 'c, T> as core::ops::deref::Deref>::deref
When trying this tool on Servo’s script
crate (which take a very long time to compile), I get this error:
error: The current compilation is going to use thin LTO buffers without running LLVM's NameAnonGlobals pass. This will likely cause errors in LLVM. Consider adding -C passes=name-anon-globals to the compiler command line.
error: aborting due to previous error
error: could not compile `script`.
To learn more, run the command again with --verbose.
Ran --emit=llvm-ir but did not find output IR
I don’t know what this means.
I’ve had to cd
into the component/script
directory of https://github.com/servo/servo because llvm-lines doesn’t seem to run in a Cargo workspace, and apply this patch (on top of revision e1cc38bea8a701108b6f2fa809f341769613b55f
, but another one should be similar).
diff --git components/script/Cargo.toml components/script/Cargo.toml
index 9f98ff3090..4152e6f870 100644
--- components/script/Cargo.toml
+++ components/script/Cargo.toml
@@ -103,7 +103,7 @@ servo_rand = { path = "../rand" }
servo_url = { path = "../url" }
smallvec = { version = "0.6", features = ["std", "union"] }
sparkle = "0.1"
-style = { path = "../style", features = ["servo"] }
+style = { path = "../style", features = ["servo", "servo-layout-2013"] }
style_traits = { path = "../style_traits" }
swapper = "0.1"
tendril = { version = "0.4.1", features = ["encoding_rs"] }
This is because Servo contributors normally don’t run cargo
directly, our mach
tool has its own configuration and runs cargo
with selected feature flags. (By the way, it would be semi-useful for non-trivial build systems to separate the "run cargo rustc
with these options" from the rest of llvm-lines
.)
fn main() {}
$ cargo llvm-lines
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Lines Copies Function name
----- ------ -------------
88 (100%) 10 (100%) (TOTAL)
25 (28.4%) 1 (10.0%) core::ops::function::FnOnce::call_once
16 (18.2%) 1 (10.0%) std::rt::lang_start
10 (11.4%) 1 (10.0%) std::rt::lang_start::{{closure}}
9 (10.2%) 1 (10.0%) core::ops::function::FnOnce::call_once{{vtable.shim}}
6 (6.8%) 1 (10.0%) <std::process::ExitCode as std::process::Termination>::report
6 (6.8%) 1 (10.0%) std::sys::unix::process::process_common::ExitCode::as_i32
5 (5.7%) 1 (10.0%) <() as std::process::Termination>::report
5 (5.7%) 1 (10.0%) core::ptr::drop_in_place
5 (5.7%) 1 (10.0%) main
1 (1.1%) 1 (10.0%) testing::main
>cargo install cargo-llvm-lines
Updating registry `https://github.com/rust-lang/crates.io-index`
Installing cargo-llvm-lines v0.1.1
Compiling winapi-build v0.1.1
Compiling winapi v0.2.8
Compiling rustc-demangle v0.1.5
Compiling libc v0.2.34
Compiling rand v0.3.18
Compiling kernel32-sys v0.2.2
Compiling tempdir v0.3.5
Compiling isatty v0.1.6
Compiling cargo-llvm-lines v0.1.1
error[E0433]: failed to resolve. Could not find `unix` in `os`
--> C:\Users\tmtu\.cargo\registry\src\github.com-1ecc6299db9ec823\cargo-llvm-lines-0.1.1\src\main.rs:174:22
|
174 | use std::os::unix::io::{AsRawFd, FromRawFd};
| ^^^^ Could not find `unix` in `os`
error[E0433]: failed to resolve. Use of undeclared type or module `AsRawFd`
--> C:\Users\tmtu\.cargo\registry\src\github.com-1ecc6299db9ec823\cargo-llvm-lines-0.1.1\src\main.rs:184:58
|
184 | Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
| ^^^^^^^ Use of undeclared type or module `AsRawFd`
error[E0433]: failed to resolve. Use of undeclared type or module `AsRawFd`
--> C:\Users\tmtu\.cargo\registry\src\github.com-1ecc6299db9ec823\cargo-llvm-lines-0.1.1\src\main.rs:190:58
|
190 | Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
| ^^^^^^^ Use of undeclared type or module `AsRawFd`
error[E0599]: no function or associated item named `from_raw_fd` found for type `std::process::Stdio` in the current scope
--> C:\Users\tmtu\.cargo\registry\src\github.com-1ecc6299db9ec823\cargo-llvm-lines-0.1.1\src\main.rs:184:13
|
184 | Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
| ^^^^^^^^^^^^^^^^^^ function or associated item not found in `std::process::Stdio`
error[E0599]: no function or associated item named `from_raw_fd` found for type `std::process::Stdio` in the current scope
--> C:\Users\tmtu\.cargo\registry\src\github.com-1ecc6299db9ec823\cargo-llvm-lines-0.1.1\src\main.rs:190:13
|
190 | Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
| ^^^^^^^^^^^^^^^^^^ function or associated item not found in `std::process::Stdio`
error: aborting due to 6 previous errors
error: failed to compile `cargo-llvm-lines v0.1.1`, intermediate artifacts can be found at `C:\Users\tmtu\AppData\Local\Temp\cargo-install.7IIKZmFJrIFc`
Caused by:
Could not compile `cargo-llvm-lines`.
To learn more, run the command again with --verbose.
Once again, ❤️ for building this, once again, in rust-lang/rust-analyzer#10065, llvm-lines was instrumental for getting rid of a major code bloat.
In that issue, llvm-lines quickly identified the leaf bloated functions, but it was not obvious why those monomorphisations are there (indeed, they turned out to be dead code). To figure that out, I used a manual workflow of ctrl+F in the .ll
file to follow call-chains of suspicious functions backwards, until I found the root cause of extra monomorphisations (in my case, drop
method in trait objects vtable).
It would be very cool If I could somehow automate this process. I think cargo-llvm-lines
could easily build a static call-graph between all monomorphizations.
I have no idea how to visualize that information in a convenient way though :(
Tried to run cargo llvm-lines
on a project of mine, got the above error message. Unfortunately it doesn't tell me which file, this is all I've got. After the error it does output some statistics, but it seems like they're only for functions from core and alloc, not any of my code or the other crates it depends on. Running on Win 10 x64. Version is 0.4.3.
> cargo llvm-lines
Compiling wasm-playground v0.1.0 (C:\Users\smmal\Desktop\code\wasm-playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.56s
Unsuccessful `cargo rustc` invocation: The system cannot find the file specified. (os error 2)
Lines Copies Function name
----- ------ -------------
189 (100%) 11 (100%) (TOTAL)
51 (27.0%) 1 (9.1%) core::alloc::global::GlobalAlloc::realloc
32 (16.9%) 1 (9.1%) core::alloc::global::GlobalAlloc::alloc_zeroed
20 (10.6%) 1 (9.1%) core::alloc::layout::Layout::from_size_align_unchecked
19 (10.1%) 1 (9.1%) __rg_realloc
16 (8.5%) 1 (9.1%) __rg_dealloc
13 (6.9%) 1 (9.1%) __rg_alloc
13 (6.9%) 1 (9.1%) __rg_alloc_zeroed
8 (4.2%) 1 (9.1%) core::alloc::layout::Layout::align
7 (3.7%) 1 (9.1%) core::num::NonZeroUsize::new_unchecked
6 (3.2%) 1 (9.1%) core::alloc::layout::Layout::size
4 (2.1%) 1 (9.1%) core::num::NonZeroUsize::get
cargo audit reported the following:
Crate: tempdir
Version: 0.3.7
Warning: unmaintained
Title: `tempdir` crate has been deprecated; use `tempfile` instead
Date: 2018-02-13
ID: RUSTSEC-2018-0017
URL: https://rustsec.org/advisories/RUSTSEC-2018-0017
Dependency tree:
tempdir 0.3.7
└── cargo-llvm-lines 0.4.23
Would probably be a good idea to switch to tempfile instead as per the advisory.
There's quite a bit of argument refactoring in the 0.4.6 to 0.4.7 diff, so I'm not sure of the precise commit, but previously cargo llvm-lines -- -Zverbose
for example would've worked, passing the -Zverbose to rustc (like cargo rustc does). perf.rust-lang.org used this support.
I think this was likely unintentional -- perhaps we could re-add that support?
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.