rust/compiler
bors b01326ab03 Auto merge of #76680 - Julian-Wollersberger:nongeneric_ensure_sufficient_stack, r=jyn514
Make `ensure_sufficient_stack()` non-generic, using cargo-llvm-lines

Inspired by [this blog post](https://blog.mozilla.org/nnethercote/2020/08/05/how-to-speed-up-the-rust-compiler-some-more-in-2020/) from `@nnethercote,` I used [cargo-llvm-lines](https://github.com/dtolnay/cargo-llvm-lines/) on the rust compiler itself, to improve it's compile time. This PR contains only one low-hanging fruit, but I also want to share some measurements.

The function `ensure_sufficient_stack()` was monomorphized 1500 times, and with it the `stacker` and `psm` crates, for a total of 1.5% of all llvm IR lines. With some trickery I convert the generic closure into a dynamic one, and thus all that code is only monomorphized once.

# Measurements
Getting these numbers took some fiddling with CLI flags and I [modified](https://github.com/Julian-Wollersberger/cargo-llvm-lines/blob/master/src/main.rs#L115) cargo-llvm-lines to read from a folder instead of invoking cargo. Commands I used:
```
./x.py clean
RUSTFLAGS="--emit=llvm-ir -C link-args=-fuse-ld=lld -Z self-profile=profile" CARGOFLAGS_BOOTSTRAP="-Ztimings" RUSTC_BOOTSTRAP=1 ./x.py build -i --stage 1 library/std

# Then manually copy all .ll files into a folder I hardcoded in cargo-llvm-lines in main.rs#L115
cd ../cargo-llvm-lines
cargo run llvm-lines
```

The result is this list (see [first 500 lines](https://github.com/Julian-Wollersberger/cargo-llvm-lines/blob/master/llvm-lines-rustc-before.txt) ), before the change:
```
  Lines            Copies        Function name
  -----            ------        -------------
  16894211 (100%)  58417 (100%)  (TOTAL)
   2223855 (13.2%)   502 (0.9%)  rustc_query_system::query::plumbing::get_query_impl::{{closure}}
   1331918 (7.9%)   1287 (2.2%)  hashbrown::raw::RawTable<T>::reserve_rehash
    774434 (4.6%)  12043 (20.6%) core::ptr::drop_in_place
    294170 (1.7%)    499 (0.9%)  rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
    245410 (1.5%)   1552 (2.7%)  psm::on_stack::with_on_stack
    210311 (1.2%)      1 (0.0%)  rustc_target::spec::load_specific
    200962 (1.2%)    513 (0.9%)  rustc_query_system::query::plumbing::get_query_impl
    190704 (1.1%)      1 (0.0%)  rustc_middle::ty::query::<impl rustc_middle::ty::context::TyCtxt>::alloc_self_profile_query_strings
    180272 (1.1%)    468 (0.8%)  rustc_query_system::query::plumbing::load_from_disk_and_cache_in_memory
    177396 (1.1%)    114 (0.2%)  rustc_query_system::query::plumbing::force_query_impl
    161134 (1.0%)    445 (0.8%)  rustc_query_system::dep_graph::graph::DepGraph<K>::with_anon_task
    141551 (0.8%)    186 (0.3%)  rustc_query_system::query::plumbing::incremental_verify_ich
    110191 (0.7%)      7 (0.0%)  rustc_middle::ty::context::_DERIVE_rustc_serialize_Decodable_D_FOR_TypeckResults::<impl rustc_serialize::serialize::Decodable<__D> for rustc_middle::ty::context::TypeckResults>::decode::{{closure}}
    108590 (0.6%)    420 (0.7%)  core::ops::function::FnOnce::call_once
     88488 (0.5%)     21 (0.0%)  rustc_query_system::dep_graph::graph::DepGraph<K>::try_mark_previous_green
     86368 (0.5%)      1 (0.0%)  rustc_middle::ty::query::stats::query_stats
     85654 (0.5%)   3973 (6.8%)  <&T as core::fmt::Debug>::fmt
     84475 (0.5%)      1 (0.0%)  rustc_middle::ty::query::Queries::try_collect_active_jobs
     81220 (0.5%)    862 (1.5%)  <hashbrown::raw::RawIterHash<T> as core::iter::traits::iterator::Iterator>::next
     77636 (0.5%)     54 (0.1%)  core::slice::sort::recurse
     66484 (0.4%)    461 (0.8%)  <hashbrown::raw::RawIter<T> as core::iter::traits::iterator::Iterator>::next
```

All `.ll` files together had 4.4GB. After my change they had 4.2GB. So a few percent less code LLVM has to process. Hurray!
Sadly, I couldn't measure an actual wall-time improvement. Watching YouTube while compiling added to much noise...

Here is the top of the list after the change:
```
  16460866 (100%)  58341 (100%)  (TOTAL)
   1903085 (11.6%)   504 (0.9%)  rustc_query_system::query::plumbing::get_query_impl::{{closure}}
   1331918 (8.1%)   1287 (2.2%)  hashbrown::raw::RawTable<T>::reserve_rehash
    777796 (4.7%)  12031 (20.6%) core::ptr::drop_in_place
    551462 (3.4%)   1519 (2.6%)  rustc_data_structures::stack::ensure_sufficient_stack::{{closure}}
```
Note that the total was reduced by 430 000 lines and `psm::on_stack::with_on_stack` has disappeared. Instead `rustc_data_structures::stack::ensure_sufficient_stack::{{closure}}` appeared. I'm confused about that one, but it seems to consist of inlined calls to `rustc_query_system::*` stuff.

Further note the other two big culprits in this list: `rustc_query_system` and `hashbrown`. These two are monomorphized many times, the query system summing to more than 20% of all lines, not even counting code that's probably inlined elsewhere.
Assuming compile times scale linearly with llvm-lines, that means a possible 20% compile time reduction.

Reducing eg. `get_query_impl` would probably need a major refactoring of the qery system though. _Everything_ in there is generic over multiple types, has associated types and passes generic Self arguments by value. Which means you can't simply make things `dyn`.

---------------------------------------
This PR is a small step to make rustc compile faster and thus make contributing to rustc less painful. Nonetheless I love Rust and I find the work around rustc fascinating :)
2020-09-21 17:32:57 +00:00
..
rustc just max_level_info 2020-09-11 09:37:51 -07:00
rustc_apfloat mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_arena Rollup merge of #76821 - est31:remove_redundant_nightly_features, r=oli-obk,Mark-Simulacrum 2020-09-20 12:08:22 +02:00
rustc_ast Rollup merge of #76890 - matthiaskrgr:matches_simpl, r=lcnr 2020-09-20 15:52:01 +02:00
rustc_ast_lowering simplfy condition in ItemLowerer::with_trait_impl_ref() 2020-09-16 23:09:57 +02:00
rustc_ast_passes use matches!() macro for simple if let conditions 2020-09-18 20:28:35 +02:00
rustc_ast_pretty Fully integrate token collection for additional AST structs 2020-09-10 17:58:14 -04:00
rustc_attr use matches!() macro for simple if let conditions 2020-09-18 20:28:35 +02:00
rustc_builtin_macros use matches!() macro for simple if let conditions 2020-09-18 20:28:35 +02:00
rustc_codegen_llvm Rollup merge of #76962 - est31:const_cstr, r=oli-obk 2020-09-21 10:40:45 +02:00
rustc_codegen_ssa Rollup merge of #76872 - khyperia:remove_declare_methods, r=eddyb 2020-09-21 10:40:35 +02:00
rustc_data_structures Auto merge of #76680 - Julian-Wollersberger:nongeneric_ensure_sufficient_stack, r=jyn514 2020-09-21 17:32:57 +00:00
rustc_driver use strip_prefix over starts_with and manual slicing based on pattern length (clippy::manual_strip) 2020-09-17 10:13:16 +02:00
rustc_error_codes Rollup merge of #76439 - GuillaumeGomez:add-error-explanation-e0755, r=pickfire,jyn514 2020-09-21 15:30:34 +02:00
rustc_errors Rollup merge of #76846 - botika:master, r=davidtwco 2020-09-21 10:40:30 +02:00
rustc_expand Remove redundant #![feature(...)] 's from compiler/ 2020-09-17 07:58:45 +02:00
rustc_feature Remove MMX from Rust 2020-09-20 15:13:11 +02:00
rustc_fs_util mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_graphviz Make graphviz font configurable 2020-09-16 08:10:06 -07:00
rustc_hir review, improve note span 2020-09-13 22:53:51 +02:00
rustc_hir_pretty mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_incremental mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_index Improve BitSet APIs 2020-08-30 11:13:18 -07:00
rustc_infer check for cycles when unifying const variables 2020-09-21 12:27:55 +02:00
rustc_interface PR feedback 2020-09-17 12:18:09 +02:00
rustc_lexer Fix typo in rustc_lexer docs 2020-09-21 05:43:39 +02:00
rustc_lint Rollup merge of #76910 - lcnr:foreign-item-like, r=oli-obk 2020-09-20 15:52:04 +02:00
rustc_llvm Update cc crate to understand aarch64-apple-darwin with clang 2020-09-18 09:22:07 -04:00
rustc_macros Fix non-determinism in generated format string. 2020-09-09 21:23:25 +10:00
rustc_metadata support const_evaluatable_checked across crate boundaries 2020-09-18 17:11:34 +02:00
rustc_middle check for cycles when unifying const variables 2020-09-21 12:27:55 +02:00
rustc_mir Auto merge of #74040 - lcnr:const-occurs-check, r=nikomatsakis 2020-09-21 12:52:09 +00:00
rustc_mir_build Rollup merge of #76890 - matthiaskrgr:matches_simpl, r=lcnr 2020-09-20 15:52:01 +02:00
rustc_parse Remove redundant #![feature(...)] 's from compiler/ 2020-09-17 07:58:45 +02:00
rustc_parse_format Remove redundant #![feature(...)] 's from compiler/ 2020-09-17 07:58:45 +02:00
rustc_passes transmute: use diagnostic item 2020-09-19 11:33:11 +02:00
rustc_plugin_impl mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_privacy Rollup merge of #76821 - est31:remove_redundant_nightly_features, r=oli-obk,Mark-Simulacrum 2020-09-20 12:08:22 +02:00
rustc_query_system update the version of itertools and parking_lot 2020-09-12 08:26:53 +02:00
rustc_resolve Rollup merge of #76890 - matthiaskrgr:matches_simpl, r=lcnr 2020-09-20 15:52:01 +02:00
rustc_save_analysis use push(char) instead of push_str(&str) to add single chars to strings 2020-09-10 13:58:41 +02:00
rustc_serialize mv compiler to compiler/ 2020-08-30 18:45:07 +03:00
rustc_session Rollup merge of #76832 - khyperia:backend_target_override, r=eddyb 2020-09-20 15:51:48 +02:00
rustc_span Auto merge of #76295 - mati865:remove-mmx, r=Amanieu,oli-obk 2020-09-21 00:43:26 +00:00
rustc_symbol_mangling Change ty.kind to a method 2020-09-04 17:47:51 +02:00
rustc_target librustc_target: Address comments 2020-09-14 17:43:06 -07:00
rustc_trait_selection Auto merge of #76886 - Aaron1011:fix/ensure-stack-predicate, r=Mark-Simulacrum 2020-09-19 09:21:22 +00:00
rustc_traits Remove redundant #![feature(...)] 's from compiler/ 2020-09-17 07:58:45 +02:00
rustc_ty Remove redundant #![feature(...)] 's from compiler/ 2020-09-17 07:58:45 +02:00
rustc_typeck Rollup merge of #76835 - matthiaskrgr:replace_prefix, r=lcnr 2020-09-21 15:30:39 +02:00