From 3c97b91c2c74b72fba5220dde98d4571dd4691cf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 21 Nov 2025 14:40:57 +0100 Subject: [PATCH] perf: Produce less progress reports --- crates/rust-analyzer/src/main_loop.rs | 119 ++++++++++++++++++++------ 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 099eed92b256..7b339fa31bc2 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -341,20 +341,23 @@ impl GlobalState { self.handle_task(&mut prime_caches_progress, task); } + let title = "Indexing"; + let cancel_token = Some("rustAnalyzer/cachePriming".to_owned()); + + let mut last_report = None; for progress in prime_caches_progress { - let (state, message, fraction, title); match progress { PrimeCachesProgress::Begin => { - state = Progress::Begin; - message = None; - fraction = 0.0; - title = "Indexing"; + self.report_progress( + title, + Progress::Begin, + None, + Some(0.0), + cancel_token.clone(), + ); } PrimeCachesProgress::Report(report) => { - state = Progress::Report; - title = report.work_type; - - message = match &*report.crates_currently_indexing { + let message = match &*report.crates_currently_indexing { [crate_name] => Some(format!( "{}/{} ({})", report.crates_done, @@ -371,38 +374,66 @@ impl GlobalState { _ => None, }; - fraction = Progress::fraction(report.crates_done, report.crates_total); + // Don't send too many notifications while batching, sending progress reports + // serializes notifications on the mainthread at the moment which slows us down + last_report = Some(( + message, + Progress::fraction(report.crates_done, report.crates_total), + report.work_type, + )); } PrimeCachesProgress::End { cancelled } => { - state = Progress::End; - message = None; - fraction = 1.0; - title = "Indexing"; - self.analysis_host.raw_database_mut().trigger_lru_eviction(); self.prime_caches_queue.op_completed(()); if cancelled { self.prime_caches_queue .request_op("restart after cancellation".to_owned(), ()); } + if let Some((message, fraction, title)) = last_report.take() { + self.report_progress( + title, + Progress::Report, + message, + Some(fraction), + cancel_token.clone(), + ); + } + self.report_progress( + title, + Progress::End, + None, + Some(1.0), + cancel_token.clone(), + ); } }; - + } + if let Some((message, fraction, title)) = last_report.take() { self.report_progress( title, - state, + Progress::Report, message, Some(fraction), - Some("rustAnalyzer/cachePriming".to_owned()), + cancel_token.clone(), ); } } Event::Vfs(message) => { let _p = tracing::info_span!("GlobalState::handle_event/vfs").entered(); - self.handle_vfs_msg(message); + let mut last_progress_report = None; + self.handle_vfs_msg(message, &mut last_progress_report); // Coalesce many VFS event into a single loop turn while let Ok(message) = self.loader.receiver.try_recv() { - self.handle_vfs_msg(message); + self.handle_vfs_msg(message, &mut last_progress_report); + } + if let Some((message, fraction)) = last_progress_report { + self.report_progress( + "Roots Scanned", + Progress::Report, + Some(message), + Some(fraction), + None, + ); } } Event::Flycheck(message) => { @@ -850,7 +881,11 @@ impl GlobalState { } } - fn handle_vfs_msg(&mut self, message: vfs::loader::Message) { + fn handle_vfs_msg( + &mut self, + message: vfs::loader::Message, + last_progress_report: &mut Option<(String, f64)>, + ) { let _p = tracing::info_span!("GlobalState::handle_vfs_msg").entered(); let is_changed = matches!(message, vfs::loader::Message::Changed { .. }); match message { @@ -907,13 +942,41 @@ impl GlobalState { ); } - self.report_progress( - "Roots Scanned", - state, - Some(message), - Some(Progress::fraction(n_done, n_total)), - None, - ); + match state { + Progress::Begin => self.report_progress( + "Roots Scanned", + state, + Some(message), + Some(Progress::fraction(n_done, n_total)), + None, + ), + // Don't send too many notifications while batching, sending progress reports + // serializes notifications on the mainthread at the moment which slows us down + Progress::Report => { + if last_progress_report.is_none() { + self.report_progress( + "Roots Scanned", + state, + Some(message.clone()), + Some(Progress::fraction(n_done, n_total)), + None, + ); + } + + *last_progress_report = + Some((message, Progress::fraction(n_done, n_total))); + } + Progress::End => { + last_progress_report.take(); + self.report_progress( + "Roots Scanned", + state, + Some(message), + Some(Progress::fraction(n_done, n_total)), + None, + ) + } + } } } }