rust-analyzer is slow to compile

Created on 10 Oct 2019  ·  57Comments  ·  Source: rust-analyzer/rust-analyzer

Both ra_hir and ra_ide_api are really slow to compiler, which makes fix & test loop rather frustrating. Note that tests are extremely fast themselves, it's compile time that hurts us badly.

We need to do something with it...

E-hard fun

Most helpful comment

image

Codegen seems to be taking an awful lot of time...

With debug=0:

image

But overall that's just a tiny improvement.

All 57 comments

image

Codegen seems to be taking an awful lot of time...

With debug=0:

image

But overall that's just a tiny improvement.

At the moment we carry around 2 versions of winapi which adds over 30 seconds to my build. I can get it down to (I think) one version of 0.2.8 being held back by mio.

@Inicola is that cargo timings with build? 88s to generate metadata on ra_hir?

Yeah, and 102s by default. Maybe there's a lot of generic code?

Hm, that reminds me that we should set debug = 1 for the dev profile, to save some disk space...

Another interesting thing is that I tried to use lld. Even though it helped quite a lot on other projects, it seems to make no difference here.

Some random -Z self-profile measurements, which don't tell us anything new:

ra_hir:

| Item                                          | Self time | % of total time | Item count | Cache hits | Blocked time | Incremental load time |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_optimize_module_passes            | 129.32s   | 35.794          | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_thin_lto_optimize                        | 75.69s    | 20.950          | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_codegen_emit_obj                  | 55.74s    | 15.429          | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| codegen_crate                                 | 36.53s    | 10.111          | 1          | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| codegen_module                                | 16.45s    | 4.553           | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_thin_lto_import                          | 13.98s    | 3.869           | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_optimize_function_passes          | 6.76s     | 1.870           | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| typeck_tables_of                              | 3.29s     | 0.910           | 2798       | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_codegen_make_bitcode              | 2.61s     | 0.723           | 199        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| evaluate_obligation                           | 1.35s     | 0.374           | 79783      | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| monomorphization_collector_graph_walk         | 1.04s     | 0.289           | 1          | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+

ra_ide_api:

| Item                                          | Self time | % of total time | Item count | Cache hits | Blocked time | Incremental load time |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_optimize_module_passes            | 166.80s   | 35.059          | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_thin_lto_optimize                        | 96.95s    | 20.377          | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_codegen_emit_obj                  | 69.66s    | 14.642          | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| codegen_crate                                 | 50.28s    | 10.568          | 1          | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_thin_lto_import                          | 26.33s    | 5.533           | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| codegen_module                                | 25.05s    | 5.266           | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_optimize_function_passes          | 10.47s    | 2.200           | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| LLVM_module_codegen_make_bitcode              | 3.14s     | 0.660           | 305        | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| normalize_projection_ty                       | 1.84s     | 0.386           | 15240      | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| monomorphization_collector_graph_walk         | 1.74s     | 0.367           | 1          | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| evaluate_obligation                           | 1.46s     | 0.307           | 74165      | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+
| codegen_fulfill_obligation                    | 1.46s     | 0.307           | 23807      | 0          | 0.00ns       | 0.00ns                |
+-----------------------------------------------+-----------+-----------------+------------+------------+--------------+-----------------------+

Will further modularization help?

Might be relevant for cargo test https://github.com/rust-lang/cargo/issues/7514

On thing that helps a bit is using lld:

λ cat ~/.cargo/config 
[build]
rustflags = [ "-C", "link-arg=-fuse-ld=lld" ]⏎

That's strange, I tried it a couple of times, and it made zero difference for RA. It does help a lot on other projects.

Since I now got a fancy desktop PC which is not generally slow here is another observation: The compile cycle does barely use any parallelism.

The following is the CPU utilization for a small edit and recompile inside a file in ra_hir on a 12 core CPU:

The whole cargo build for this picture took 12s - so it's not super annoying. But it looks like it could go a lot faster if more resources are actually used. But I guess that is more likely a rustc than an actual rust-analyzer issue - unless the project is restructured to be more suitable to for parallelism (crates which are not that dependend on each other?).

I think small, incremental edits parallelize inherently worse, because there's less to compile. Still, it's not so bad:

image

But it's surprising how much debug info slows things down. Same scenario, touch crates/ra_hir/src/db.rs; cargo build --release -p ra_lsp_server, but with debug = 0 instead of 1:

image

How could one disable debug=0 constantly without an extra flag without having to constantly stash the change in Cargo.toml as soon as there's an update?

That's how, but you might not need to stash that often.

I generally use pull --rebase with autostash, so it doesn't come up most of the time.

Hm, should we put debug=0 into Cargo.toml? I think I personally can live with that, especially if it makes printf debugging faster :-)

We loose line numbers in backtraces, but I think I rarely look at backtraces (but we should retain debug=1 for releases, so that folks can get a useful backtraces from the debugger).

On the side note, one of the things I miss most from IntelliJ is the ability to colorize and linkify backtraces. If we could link rust::paths from backtraces to functions, that would be sooo helpful.

Hm, should we put debug=0 into Cargo.toml? I think I personally can live with that, especially if it makes printf debugging faster :-)

That depends on whether you're testing on debug or release builds. Re backtraces, unfortunately rust-analyzer pretty much never crashes for me. I've used the debug info for profiling, but I can enable it manually.

Well, I use rust-analyzer always with install-ra, which means afaic that I use release all the times. :/

It feels like it became significantly works for --release since we've introduced ra_ide_db crate, because now we repeatedly monomorphise hir for the same database in different crates.

Some measurements from today and a time before ra_ide_db introduction https://gist.github.com/matklad/9657836aa0a9ad226a95b6f18d55b3fc

image

image

:( :( :(

I haven't looked over the code (not sure what the polymorphic code is), but is there a way to avoid that, maybe by introducing monomorphic wrappers?

So "introducing monomorphic wrappers" is exactly what ra_ide_db did, and it made things worse.

Ie, making DB non-generic does not work (or, rather, makes things worse), because all functions are still generic, but are now monomorphised in each crate that uses a non-generic database.

because all functions are still generic

Do you mean things like impl<'db, DB: HirDatabase> Semantics<'db, DB> that are still generic over the database? Can they use RootDatabase instead?

That as well, but mostly all query definitions, like infer_query.

(though, I still haven't really debugged this properly, my understanding of how monomorphisation happens might be wrong)

I can't try right now, but I'm curious what happens on a non-LTO build. It seemed to me that half of the build time was spent during linking.

with lto=false it is somewhat faster, but the general picture is the same

https://gist.github.com/matklad/c80618d9328546ca28f06ebe9022a327

image

Ok, looks like my analysis about monomorphisations was only partially correct. I've switch everything to dynamic dispatch in https://github.com/matklad/rust-analyzer/commit/68304de289ba88dda20e242c841859a8348d921f

It reduced the total compile time somewhat, but, contrary to what I've expected, every one of the big crates still takes a long time to compile.

https://gist.github.com/matklad/4a38367f0b2fd8da1c5c4f7c2297c00f

image

I think it would be very useful to compare self-profile data from the dyn commint and from the corrspondig commit before dyn-ing everything.

Is that with lto=false?

Nope, that's with lto.

Total build time for dyn is

real 210.67s
user 1570.88s
sys  15.58s
rss  966300k

for impl is

real 306.74s
user 2288.41s
sys  19.79s
rss  1061588k

Perf is essentially the same, binary is slightly smaller:

λ ./target/rust-analyzer-dyn analysis-stats ~/projects/rustraytracer/
Database loaded, 55 roots, 75.137501ms
Crates in this dir: 4
Total modules found: 40
Total declarations: 309
Total functions: 175
Item Collection: 3.382379153s, 0b allocated 0b resident
Total expressions: 4101                                                  
Expressions of unknown type: 187 (4%)
Expressions of partially unknown type: 94 (2%)
Type mismatches: 38
Inference: 5.032461187s, 0b allocated 0b resident
Total: 8.414847361s, 0b allocated 0b resident

17:46:38|~/projects/rust-analyzer|master✓
λ ./target/rust-analyzer-impl analysis-stats ~/projects/rustraytracer/
Database loaded, 55 roots, 72.812239ms
Crates in this dir: 4
Total modules found: 40
Total declarations: 309
Total functions: 175
Item Collection: 3.401339997s, 0b allocated 0b resident
Total expressions: 4101                                                  
Expressions of unknown type: 187 (4%)
Expressions of partially unknown type: 94 (2%)
Type mismatches: 38
Inference: 5.013217611s, 0b allocated 0b resident
Total: 8.414570169s, 0b allocated 0b resident

λ exa -l -all target/
.rwxr-xr-x 21M matklad 13 Mar 17:47 rust-analyzer-dyn
.rwxr-xr-x 24M matklad 13 Mar 17:47 rust-analyzer-impl

No significant difference in debug build-times, about a minute for each.

I wonder why your binary is so small (21 MB). The one on GitHub is 27 MB and mine is 28.

EDIT: ah, strip -s does that.

And the one on GitHub is presumably linked statically (but still stripped).

Maybe cargo-llvm-lines could help us identify some hot spots.

Some results on the rust-analyzer crate:

  Lines        Copies         Function name
  -----        ------         -------------
 483559 (100%)  15673 (100%)  (TOTAL)
  15650 (3.2%)   1263 (8.1%)  core::ptr::drop_in_place
  13702 (2.8%)     34 (0.2%)  alloc::raw_vec::RawVec<T,A>::grow
  11638 (2.4%)    182 (1.2%)  core::result::Result<T,E>::map
  11547 (2.4%)    178 (1.1%)  core::result::Result<T,E>::map_err
   8855 (1.8%)     35 (0.2%)  rust_analyzer::main_loop::result_to_task
   8249 (1.7%)     59 (0.4%)  <serde_json::value::de::MapDeserializer as serde::de::MapAccess>::next_key_seed
   7463 (1.5%)     58 (0.4%)  serde_json::value::de::visit_object
   7389 (1.5%)     32 (0.2%)  serde::ser::Serializer::collect_seq
   7324 (1.5%)     35 (0.2%)  rust_analyzer::main_loop::PoolDispatcher::parse
   7063 (1.5%)     73 (0.5%)  core::iter::traits::iterator::Iterator::try_fold
   6803 (1.4%)    131 (0.8%)  core::result::Result<T,E>::unwrap_or_else
   6173 (1.3%)     48 (0.3%)  serde_json::value::de::visit_array
   5375 (1.1%)     68 (0.4%)  <serde_json::value::ser::SerializeMap as serde::ser::SerializeMap>::serialize_value
   5214 (1.1%)     88 (0.6%)  core::option::Option<T>::map
   4465 (0.9%)     19 (0.1%)  hashbrown::raw::RawTable<T>::rehash_in_place
   4340 (0.9%)     35 (0.2%)  serde_json::value::de::<impl serde::de::Deserializer for serde_json::value::Value>::deserialize_struct
   3771 (0.8%)     30 (0.2%)  rust_analyzer::main_loop::PoolDispatcher::on
   3728 (0.8%)     49 (0.3%)  <serde_json::value::de::SeqDeserializer as serde::de::SeqAccess>::next_element_seed
   3429 (0.7%)     49 (0.3%)  <serde_json::value::de::MapDeserializer as serde::de::MapAccess>::next_value_seed
   3332 (0.7%)     58 (0.4%)  core::option::Option<T>::ok_or_else
   3193 (0.7%)    145 (0.9%)  serde_json::value::to_value
   3141 (0.6%)     30 (0.2%)  lsp_server::msg::Request::extract
   3083 (0.6%)     39 (0.2%)  alloc::vec::Vec<T>::extend_desugared
   3059 (0.6%)     19 (0.1%)  hashbrown::raw::RawTable<T>::resize
   2856 (0.6%)     24 (0.2%)  hashbrown::raw::RawTable<T>::find
   2732 (0.6%)     60 (0.4%)  core::ptr::swap_nonoverlapping_one
   2720 (0.6%)     68 (0.4%)  serde::ser::SerializeMap::serialize_entry
   2655 (0.5%)     59 (0.4%)  <serde_json::value::de::BorrowedCowStrDeserializer as serde::de::Deserializer>::deserialize_any
   2625 (0.5%)     31 (0.2%)  <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
   2314 (0.5%)      1 (0.0%)  rust_analyzer::cli::analysis_stats::analysis_stats
   2290 (0.5%)     80 (0.5%)  alloc::alloc::box_free
   2229 (0.5%)     45 (0.3%)  crossbeam_channel::context::Context::with::{{closure}}
   2133 (0.4%)     27 (0.2%)  core::iter::traits::exact_size::ExactSizeIterator::len
   2091 (0.4%)     41 (0.3%)  alloc::raw_vec::RawVec<T,A>::current_memory
   2065 (0.4%)     59 (0.4%)  serde::de::Visitor::visit_string

And ra_ide_db:

    Finished dev [unoptimized] target(s) in 1m 05s
  Lines        Copies         Function name
  -----        ------         -------------
1620843 (100%)  62960 (100%)  (TOTAL)
  61069 (3.8%)   5316 (8.4%)  core::ptr::drop_in_place
  51419 (3.2%)     47 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade
  48978 (3.0%)     94 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::probe
  36812 (2.3%)    561 (0.9%)  core::result::Result<T,E>::map_err
  35226 (2.2%)    636 (1.0%)  core::option::Option<T>::map
  34771 (2.1%)     47 (0.1%)  <salsa::derived::slot::Slot<DB,Q,MP> as salsa::dependency::DatabaseSlot<DB>>::maybe_changed_since
  34658 (2.1%)     86 (0.1%)  alloc::raw_vec::RawVec<T,A>::grow
  30141 (1.9%)    498 (0.8%)  core::option::Option<T>::ok_or_else
  26176 (1.6%)    571 (0.9%)  core::ptr::swap_nonoverlapping_one
  19537 (1.2%)    249 (0.4%)  alloc::sync::Arc<T>::new
  19045 (1.2%)    196 (0.3%)  core::iter::traits::iterator::Iterator::try_fold
  18565 (1.1%)     79 (0.1%)  hashbrown::raw::RawTable<T>::rehash_in_place
  18207 (1.1%)    153 (0.2%)  hashbrown::raw::RawTable<T>::find
  18146 (1.1%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::abort_selection
  17757 (1.1%)    343 (0.5%)  core::result::Result<T,E>::unwrap_or_else
  16966 (1.0%)     47 (0.1%)  salsa::derived::slot::PanicGuard<DB,Q,MP>::overwrite_placeholder
  13416 (0.8%)     43 (0.1%)  std::sync::mpsc::Sender<T>::send
  12719 (0.8%)     79 (0.1%)  hashbrown::raw::RawTable<T>::resize
  12389 (0.8%)     43 (0.1%)  std::sync::mpsc::shared::Packet<T>::try_recv
  12304 (0.8%)    342 (0.5%)  alloc::sync::Arc<T>::drop_slow
  12210 (0.8%)     47 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::sweep
  11844 (0.7%)     47 (0.1%)  salsa::derived::slot::Memo<DB,Q>::validate_memoized_value
  11610 (0.7%)     43 (0.1%)  std::sync::mpsc::Receiver<T>::recv
  11452 (0.7%)    166 (0.3%)  core::result::Result<T,E>::map
  11395 (0.7%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::try_recv
  11000 (0.7%)     44 (0.1%)  smallvec::SmallVec<A>::try_grow
  10241 (0.6%)     77 (0.1%)  hashbrown::raw::RawTable<T>::new_uninitialized
  10017 (0.6%)    665 (1.1%)  core::ptr::read
   9933 (0.6%)     77 (0.1%)  hashbrown::raw::RawTable<T>::try_with_capacity
   9768 (0.6%)     44 (0.1%)  std::sync::mpsc::sync::Packet<T>::drop_port
   9729 (0.6%)     47 (0.1%)  salsa::lru::LruData<Node>::insert_new
   9682 (0.6%)     47 (0.1%)  salsa::lru::Lru<Node>::record_use
   9458 (0.6%)    291 (0.5%)  <alloc::vec::Vec<T> as core::ops::index::IndexMut<I>>::index_mut
   9429 (0.6%)    347 (0.6%)  alloc::alloc::box_free
   9417 (0.6%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::recv
   9417 (0.6%)     43 (0.1%)  std::sync::mpsc::sync::Packet<T>::recv
   9027 (0.6%)    177 (0.3%)  alloc::raw_vec::RawVec<T,A>::current_memory
   8930 (0.6%)     47 (0.1%)  salsa::lru::LruData<Node>::promote_yellow_to_green
   8624 (0.5%)     44 (0.1%)  <std::sync::mpsc::shared::Packet<T> as core::ops::drop::Drop>::drop
   8453 (0.5%)     47 (0.1%)  salsa::runtime::Runtime<DB>::execute_query_implementation
   8154 (0.5%)    196 (0.3%)  <ra_ide_db::RootDatabase as salsa::Database>::salsa_event
   8137 (0.5%)    158 (0.3%)  hashbrown::raw::RawTable<T>::rehash_in_place::{{closure}}
   8020 (0.5%)    564 (0.9%)  salsa::derived::slot::Slot<DB,Q,MP>::probe::{{closure}}
   8004 (0.5%)     43 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::try_recv
   7913 (0.5%)     47 (0.1%)  <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch
   7664 (0.5%)      1 (0.0%)  ra_ide_db::change::<impl ra_ide_db::RootDatabase>::per_query_memory_usage
   7481 (0.5%)    324 (0.5%)  core::mem::replace
   7396 (0.5%)     43 (0.1%)  std::sync::mpsc::sync::Packet<T>::wakeup_senders
   7391 (0.5%)     15 (0.0%)  salsa::interned::InternedStorage<DB,Q>::intern_index
   7360 (0.5%)    320 (0.5%)  core::fmt::ArgumentV1::new
   7285 (0.4%)     47 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::register_with_in_progress_thread
   7184 (0.4%)    342 (0.5%)  <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop
   7052 (0.4%)     43 (0.1%)  std::sync::mpsc::shared::Packet<T>::abort_selection
   6840 (0.4%)    342 (0.5%)  core::alloc::layout::Layout::for_value
   6708 (0.4%)     43 (0.1%)  std::sync::mpsc::shared::Packet<T>::recv
   6593 (0.4%)     43 (0.1%)  std::sync::mpsc::shared::Packet<T>::send
   6399 (0.4%)     79 (0.1%)  hashbrown::raw::RawTable<T>::reserve_rehash
   6391 (0.4%)     77 (0.1%)  hashbrown::raw::RawTable<T>::find_insert_slot
   6364 (0.4%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::decrement
   6149 (0.4%)     43 (0.1%)  std::sync::mpsc::sync::wait_timeout_receiver
   6134 (0.4%)     72 (0.1%)  hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S>>::rustc_entry
   6116 (0.4%)     44 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::pop
   6028 (0.4%)     44 (0.1%)  <std::sync::mpsc::stream::Packet<T> as core::ops::drop::Drop>::drop
   5977 (0.4%)     43 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::recv
   5848 (0.4%)     43 (0.1%)  std::sync::mpsc::shared::Packet<T>::decrement
   5734 (0.4%)     47 (0.1%)  salsa::lru::LruData<Node>::promote_red_to_green
   5687 (0.4%)     47 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::read
   5635 (0.3%)    670 (1.1%)  core::mem::maybe_uninit::MaybeUninit<T>::assume_init
   5547 (0.3%)     43 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::upgrade
   5504 (0.3%)     43 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::send
   5332 (0.3%)     43 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::abort_selection
   5324 (0.3%)     44 (0.1%)  <std::sync::mpsc::sync::Packet<T> as core::ops::drop::Drop>::drop
   5226 (0.3%)     78 (0.1%)  <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
   5205 (0.3%)    343 (0.5%)  alloc::boxed::Box<T>::into_unique
   4988 (0.3%)    344 (0.5%)  alloc::raw_vec::RawVec<T,A>::grow::{{closure}}
   4859 (0.3%)     43 (0.1%)  std::sync::mpsc::sync::wait
   4816 (0.3%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::do_send
   4806 (0.3%)    178 (0.3%)  <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
   4773 (0.3%)     43 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::with_additions
   4753 (0.3%)     97 (0.2%)  core::iter::traits::iterator::Iterator::find::check::{{closure}}
   4601 (0.3%)     43 (0.1%)  std::sync::mpsc::sync::abort_selection
   4568 (0.3%)    571 (0.9%)  core::ptr::swap_nonoverlapping
   4429 (0.3%)     12 (0.0%)  rayon_core::join::join_context::{{closure}}
   4418 (0.3%)     47 (0.1%)  salsa::lru::LruData<Node>::record_use
   4371 (0.3%)     47 (0.1%)  salsa::derived::slot::Memo<DB,Q>::check_durability
   4269 (0.3%)     45 (0.1%)  <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
   4257 (0.3%)     43 (0.1%)  std::sync::mpsc::stream::Packet<T>::send
   4170 (0.3%)     94 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade::{{closure}}
   4137 (0.3%)    470 (0.7%)  core::cell::UnsafeCell<T>::new
   4094 (0.3%)    178 (0.3%)  core::ptr::slice_from_raw_parts_mut
   4085 (0.3%)     43 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::alloc
   4059 (0.3%)     72 (0.1%)  hashbrown::raw::RawTable<T>::insert_no_grow
   4039 (0.2%)     90 (0.1%)  core::option::Option<T>::unwrap_or_else
   4002 (0.2%)    667 (1.1%)  core::intrinsics::copy_nonoverlapping
   4002 (0.2%)     95 (0.2%)  core::result::Result<T,E>::unwrap
   3984 (0.2%)     81 (0.1%)  alloc::vec::Vec<T>::push
   3948 (0.2%)    141 (0.2%)  <salsa::derived::slot::Slot<DB,Q,MP> as salsa::dependency::DatabaseSlot<DB>>::maybe_changed_since::{{closure}}
   3910 (0.2%)     44 (0.1%)  std::sync::mpsc::mpsc_queue::Queue<T>::pop
   3904 (0.2%)     47 (0.1%)  std::collections::hash::map::Entry<K,V>::or_insert_with
   3870 (0.2%)     43 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::push
   3825 (0.2%)    765 (1.2%)  core::mem::size_of
   3810 (0.2%)    617 (1.0%)  core::mem::manually_drop::ManuallyDrop<T>::new
   3747 (0.2%)     72 (0.1%)  std::collections::hash::map::map_entry
   3741 (0.2%)     43 (0.1%)  std::sync::mpsc::channel

I'm not sure how actionable these are.

Yeah... I was hoping it would show us if there were a lot of monomorphized things we could reduce.

@lnicola @kjeremy Note that RawVec::grow, which is pretty high on both of these lists, was recently changed to be mostly non generic in https://github.com/rust-lang/rust/pull/72013. Another similar optimization was done for iterator methods in https://github.com/rust-lang/rust/pull/72166, so they now use try_fold less, which is also pretty high on these lists.

Both PRs reduced the number of llvm-ir lines generated and improved compile time. They will land on stable in next Rust release in July, so until that, you might want to measure with cargo-llvm-lines on nightly to account for these improvements :wink:

@panstromek thanks for the heads-up. I ran it again on ra_ide_db, it seems worse?


ra_ide_db LLVM lines

  Lines           Copies        Function name
  -----           ------        -------------
  1664810 (100%)  65419 (100%)  (TOTAL)
    73271 (4.4%)   6095 (9.3%)  core::ptr::drop_in_place
    55793 (3.4%)     51 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade
    53146 (3.2%)    102 (0.2%)  salsa::derived::slot::Slot<DB,Q,MP>::probe
    37731 (2.3%)     51 (0.1%)  <salsa::derived::slot::Slot<DB,Q,MP> as salsa::dependency::DatabaseSlot<DB>>::maybe_changed_since
    32628 (2.0%)    539 (0.8%)  core::option::Option<T>::ok_or_else
    30708 (1.8%)    534 (0.8%)  core::option::Option<T>::map
    28252 (1.7%)    616 (0.9%)  core::ptr::swap_nonoverlapping_one
    21528 (1.3%)    271 (0.4%)  alloc::sync::Arc<T>::new
    20210 (1.2%)     86 (0.1%)  hashbrown::raw::RawTable<T>::rehash_in_place
    19754 (1.2%)    166 (0.3%)  hashbrown::raw::RawTable<T>::find
    19411 (1.2%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::abort_selection
    18755 (1.1%)    363 (0.6%)  core::result::Result<T,E>::unwrap_or_else
    18410 (1.1%)     51 (0.1%)  salsa::derived::slot::PanicGuard<DB,Q,MP>::overwrite_placeholder
    17549 (1.1%)    180 (0.3%)  core::iter::traits::iterator::Iterator::try_fold
    15720 (0.9%)    236 (0.4%)  core::result::Result<T,E>::map_err
    14845 (0.9%)    371 (0.6%)  <alloc::sync::Weak<T> as core::ops::drop::Drop>::drop
    14664 (0.9%)     47 (0.1%)  std::sync::mpsc::Sender<T>::send
    13846 (0.8%)     86 (0.1%)  hashbrown::raw::RawTable<T>::resize
    13364 (0.8%)    371 (0.6%)  alloc::sync::Weak<T>::inner
    12852 (0.8%)     51 (0.1%)  salsa::derived::slot::Memo<DB,Q>::validate_memoized_value
    12736 (0.8%)     49 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::sweep
    12690 (0.8%)     47 (0.1%)  std::sync::mpsc::Receiver<T>::recv
    12658 (0.8%)     47 (0.1%)  std::sync::mpsc::shared::Packet<T>::try_recv
    12384 (0.7%)     48 (0.1%)  std::sync::mpsc::sync::Packet<T>::drop_port
    12032 (0.7%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::try_recv
    12000 (0.7%)     48 (0.1%)  smallvec::SmallVec<A>::try_grow
    11515 (0.7%)     47 (0.1%)  std::sync::mpsc::sync::Packet<T>::wakeup_senders
    11303 (0.7%)     89 (0.1%)  alloc::raw_vec::RawVec<T,A>::grow_amortized
    11039 (0.7%)     83 (0.1%)  hashbrown::raw::RawTable<T>::new_uninitialized
    10815 (0.6%)    718 (1.1%)  core::ptr::read
    10726 (0.6%)    173 (0.3%)  core::alloc::layout::Layout::array
    10707 (0.6%)     83 (0.1%)  hashbrown::raw::RawTable<T>::try_with_capacity
    10557 (0.6%)     51 (0.1%)  salsa::lru::LruData<Node>::insert_new
    10353 (0.6%)     51 (0.1%)  salsa::lru::Lru<Node>::record_use
    10293 (0.6%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::recv
    10239 (0.6%)    377 (0.6%)  alloc::alloc::box_free
     9823 (0.6%)     47 (0.1%)  std::sync::mpsc::sync::Packet<T>::recv
     9690 (0.6%)     51 (0.1%)  salsa::lru::LruData<Node>::promote_yellow_to_green
     9639 (0.6%)    189 (0.3%)  alloc::raw_vec::RawVec<T,A>::current_memory
     9169 (0.6%)     51 (0.1%)  salsa::runtime::Runtime<DB>::execute_query_implementation
     9030 (0.5%)    212 (0.3%)  <ra_ide_db::RootDatabase as salsa::Database>::salsa_event
     8976 (0.5%)     48 (0.1%)  <std::sync::mpsc::shared::Packet<T> as core::ops::drop::Drop>::drop
     8858 (0.5%)    172 (0.3%)  hashbrown::raw::RawTable<T>::rehash_in_place::{{closure}}
     8700 (0.5%)    612 (0.9%)  salsa::derived::slot::Slot<DB,Q,MP>::probe::{{closure}}
     8579 (0.5%)     51 (0.1%)  <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch
     8468 (0.5%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::try_recv
     8380 (0.5%)     17 (0.0%)  salsa::interned::InternedStorage<DB,Q>::intern_index
     8072 (0.5%)    350 (0.5%)  core::mem::replace
     7906 (0.5%)      1 (0.0%)  ra_ide_db::change::<impl ra_ide_db::RootDatabase>::per_query_memory_usage
     7905 (0.5%)     51 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::register_with_in_progress_thread
     7843 (0.5%)    341 (0.5%)  core::fmt::ArgumentV1::new
     7420 (0.4%)    371 (0.6%)  core::alloc::layout::Layout::for_value
     7332 (0.4%)     47 (0.1%)  std::sync::mpsc::shared::Packet<T>::recv
     7285 (0.4%)     47 (0.1%)  std::sync::mpsc::shared::Packet<T>::abort_selection
     6966 (0.4%)     86 (0.1%)  hashbrown::raw::RawTable<T>::reserve_rehash
     6889 (0.4%)     83 (0.1%)  hashbrown::raw::RawTable<T>::find_insert_slot
     6721 (0.4%)     47 (0.1%)  std::sync::mpsc::sync::wait_timeout_receiver
     6666 (0.4%)     78 (0.1%)  hashbrown::rustc_entry::<impl hashbrown::map::HashMap<K,V,S>>::rustc_entry
     6363 (0.4%)     47 (0.1%)  std::sync::mpsc::shared::Packet<T>::send
     6288 (0.4%)     48 (0.1%)  <std::sync::mpsc::stream::Packet<T> as core::ops::drop::Drop>::drop
     6251 (0.4%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::recv
     6251 (0.4%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::decrement
     6222 (0.4%)     51 (0.1%)  salsa::lru::LruData<Node>::promote_red_to_green
     6171 (0.4%)     51 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::read
     6093 (0.4%)    723 (1.1%)  core::mem::maybe_uninit::MaybeUninit<T>::assume_init
     5922 (0.4%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::upgrade
     5734 (0.3%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::send
     5687 (0.3%)     47 (0.1%)  std::sync::mpsc::shared::Packet<T>::decrement
     5664 (0.3%)     48 (0.1%)  <std::sync::mpsc::sync::Packet<T> as core::ops::drop::Drop>::drop
     5664 (0.3%)     48 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::pop
     5628 (0.3%)     84 (0.1%)  <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
     5567 (0.3%)    371 (0.6%)  <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop
     5546 (0.3%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::abort_selection
     5311 (0.3%)     47 (0.1%)  std::sync::mpsc::sync::wait
     5178 (0.3%)     14 (0.0%)  rayon_core::join::join_context::{{closure}}
     5103 (0.3%)    189 (0.3%)  <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
     5096 (0.3%)    104 (0.2%)  core::iter::traits::iterator::Iterator::find::check::{{closure}}
     5076 (0.3%)     47 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::with_additions
     5029 (0.3%)     47 (0.1%)  std::sync::mpsc::sync::abort_selection
     4982 (0.3%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::do_send
     4928 (0.3%)    616 (0.9%)  core::ptr::swap_nonoverlapping
     4794 (0.3%)     51 (0.1%)  salsa::lru::LruData<Node>::record_use
     4743 (0.3%)     51 (0.1%)  salsa::derived::slot::Memo<DB,Q>::check_durability
     4522 (0.3%)    102 (0.2%)  salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade::{{closure}}
     4512 (0.3%)     47 (0.1%)  std::sync::mpsc::stream::Packet<T>::send
     4507 (0.3%)    512 (0.8%)  core::cell::UnsafeCell<T>::new
     4397 (0.3%)     78 (0.1%)  hashbrown::raw::RawTable<T>::insert_no_grow
     4347 (0.3%)    189 (0.3%)  core::ptr::slice_from_raw_parts_mut
     4320 (0.3%)    720 (1.1%)  core::intrinsics::copy_nonoverlapping
     4309 (0.3%)     96 (0.1%)  core::option::Option<T>::unwrap_or_else
     4284 (0.3%)    153 (0.2%)  <salsa::derived::slot::Slot<DB,Q,MP> as salsa::dependency::DatabaseSlot<DB>>::maybe_changed_since::{{closure}}
     4270 (0.3%)     45 (0.1%)  <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
     4236 (0.3%)     51 (0.1%)  std::collections::hash::map::Entry<K,V>::or_insert_with
     4176 (0.3%)     85 (0.1%)  alloc::vec::Vec<T>::push
     4138 (0.2%)    373 (0.6%)  alloc::boxed::Box<T>::leak
     4136 (0.2%)     98 (0.1%)  core::result::Result<T,E>::unwrap
     4104 (0.2%)    667 (1.0%)  core::mem::manually_drop::ManuallyDrop<T>::new
     4090 (0.2%)    818 (1.3%)  core::mem::size_of
     4089 (0.2%)     47 (0.1%)  std::sync::mpsc::channel
     4059 (0.2%)    371 (0.6%)  alloc::sync::Arc<T>::drop_slow
     4059 (0.2%)     78 (0.1%)  std::collections::hash::map::map_entry
     4042 (0.2%)     47 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::alloc
     4023 (0.2%)     51 (0.1%)  salsa::derived::DerivedStorage<DB,Q,MP>::slot
     3976 (0.2%)     48 (0.1%)  std::sync::mpsc::mpsc_queue::Queue<T>::pop
     3948 (0.2%)     47 (0.1%)  std::sync::mpsc::spsc_queue::Queue<T,ProducerAddition,ConsumerAddition>::push
     3840 (0.2%)     48 (0.1%)  std::sys_common::poison::map_result
     3830 (0.2%)    121 (0.2%)  <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
     3744 (0.2%)     48 (0.1%)  std::sync::mpsc::shared::Packet<T>::drop_chan
     3676 (0.2%)    122 (0.2%)  <alloc::vec::Vec<T> as core::ops::index::IndexMut<I>>::index_mut
     3627 (0.2%)     93 (0.1%)  salsa::QueryTable<DB,Q>::get::{{closure}}
     3612 (0.2%)     84 (0.1%)  <hashbrown::raw::RawTable<T> as core::ops::drop::Drop>::drop
     3546 (0.2%)    698 (1.1%)  core::ptr::write
     3406 (0.2%)    566 (0.9%)  core::ptr::unique::Unique<T>::cast
     3360 (0.2%)     84 (0.1%)  hashbrown::raw::calculate_layout
     3319 (0.2%)     51 (0.1%)  salsa::derived::slot::Slot<DB,Q,MP>::evict
     3318 (0.2%)     12 (0.0%)  rayon::iter::plumbing::bridge_producer_consumer::helper
     3312 (0.2%)     48 (0.1%)  smallvec::SmallVec<A>::try_reserve
     3296 (0.2%)     28 (0.0%)  <rayon_core::job::StackJob<L,F,R> as rayon_core::job::Job>::execute
     3243 (0.2%)     47 (0.1%)  std::sync::mpsc::oneshot::Packet<T>::new
     3216 (0.2%)     48 (0.1%)  std::sync::mpsc::stream::Packet<T>::drop_port
     3149 (0.2%)     47 (0.1%)  std::sync::mpsc::mpsc_queue::Node<T>::new
     3082 (0.2%)    134 (0.2%)  core::ptr::slice_from_raw_parts

It feels like we're getting slower and slower:

image

To things jump at me as odd:

  • it feels like ssr should not be that heavy
  • chalk is too light

On Wednesday, 1 July 2020, Laurențiu Nicola notifications@github.com
wrote:

It feels like we're getting slower and slower:

[image: image]
https://user-images.githubusercontent.com/308347/86206821-f093b080-bb75-11ea-815d-9973bee870cb.png


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/rust-analyzer/rust-analyzer/issues/1987#issuecomment-652202248,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AANB3M7FRVZECURZQ77T3GTRZLDOTANCNFSM4I7OUNRA
.

  • SSR isn't heavy, Semantics is
  • I'll tell Niko that chalk-solve builds too quickly (chalk-parse takes ages)

After #5242:

image

One of my tests is to compile a new crate containing only this code:

use hir::Semantics;
use ra_syntax::{ast, AstNode, SyntaxNode};

pub struct MatchFinder<'db> {
    sema: Semantics<'db, ra_ide_db::RootDatabase>,
}

impl<'db> MatchFinder<'db> {
    pub fn new(db: &'db ra_ide_db::RootDatabase) -> MatchFinder<'db> {
        MatchFinder { sema: Semantics::new(db) }
    }

    pub fn find_matches(&self, code: &SyntaxNode) {
        if let Some(macro_call) = ast::MacroCall::cast(code.clone()) {
            self.sema.expand(&macro_call);
        }
    }
}

It takes 11.5 seconds (vs. ~35 last week).

Much more reasonable!

Substantial amount of the rest seems to be serde-generated code. Not sure how to combat that....

@lnicola do you have up-to-date CPU usage metrics over time?
Combining them with crates build chart would show bottlenecks where only a few cores are used.

We're pretty good on that front:

cargo-timing-20200707T083110Z.zip

Yeah, overall CPU usage looks very reasonable with exception of small 5 seconds window where only 3 threads are properly utilized.

16 thread CPU reveals some bottlenecks though:
cargo-timing-20200707T103522Z.zip

I wonder how much do we pay for may AST methods being trait methods. It might make sense to experiment with generating all methods as inherent methods, and then implementing traits via delegation to inherent methods. This will also reduce the amount of imports we od.

We should also try the self-profiling feature. Last time I wasn't really able to understand the profile output -- it seemed to me that ThinLTO took up to 80 seconds for some CGUs, but I didn't have a baseline to compare it with.

Let's close this: we implemented a couple of optimization in this space recently, and I feel that the compile times are reasonable .

One of the optimizations was to fix thermal throttling bug in my laptop: https://github.com/rust-analyzer/rust-analyzer/issues/5903#issuecomment-683181883 =/

One of the optimizations was to fix thermal throttling bug in my laptop

Wrong link?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bdashore3 picture bdashore3  ·  30Comments

ninjasource picture ninjasource  ·  33Comments

Veetaha picture Veetaha  ·  27Comments

matklad picture matklad  ·  28Comments

suhr picture suhr  ·  33Comments