From 5adad1a8adc6bcd46fffa2adb2411782a32b7623 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 28 Dec 2025 11:43:08 +0100 Subject: [PATCH] perf: Reduce channel lock contention for drop-threads --- src/tools/rust-analyzer/crates/span/src/map.rs | 17 ++++++++++++++++- .../rust-analyzer/crates/syntax/src/lib.rs | 13 ++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/span/src/map.rs b/src/tools/rust-analyzer/crates/span/src/map.rs index 7faf6f1b1a68..f5c083a9f650 100644 --- a/src/tools/rust-analyzer/crates/span/src/map.rs +++ b/src/tools/rust-analyzer/crates/span/src/map.rs @@ -163,7 +163,22 @@ unsafe impl Send for SendPtr {} let (sender, receiver) = std::sync::mpsc::channel::<(SendPtr, fn(SendPtr))>(); std::thread::Builder::new() .name("SpanMapDropper".to_owned()) - .spawn(move || receiver.iter().for_each(|(b, drop)| drop(b))) + .spawn(move || { + loop { + // block on a receive + if let Ok((b, drop)) = receiver.recv() { + drop(b); + } + // then drain the entire channel + while let Ok((b, drop)) = receiver.try_recv() { + drop(b); + } + // and sleep for a bit + std::thread::sleep(std::time::Duration::from_millis(100)); + } + // why do this over just a `receiver.iter().for_each(drop)`? To reduce contention on the channel lock. + // otherwise this thread will constantly wake up and sleep again. + }) .unwrap(); sender }) diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index 9e3083066c94..d36019514016 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -218,7 +218,18 @@ fn drop(&mut self) { let (sender, receiver) = std::sync::mpsc::channel::(); std::thread::Builder::new() .name("ParseNodeDropper".to_owned()) - .spawn(move || receiver.iter().for_each(drop)) + .spawn(move || { + loop { + // block on a receive + _ = receiver.recv(); + // then drain the entire channel + while let Ok(_) = receiver.try_recv() {} + // and sleep for a bit + std::thread::sleep(std::time::Duration::from_millis(100)); + } + // why do this over just a `receiver.iter().for_each(drop)`? To reduce contention on the channel lock. + // otherwise this thread will constantly wake up and sleep again. + }) .unwrap(); sender })