Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21357 from Veykril/push-rsulypnywlsv
Drop AstIdMap asynchronously
Lukas Wirth 4 months ago
parent a3bf20f · parent 3f53ead · commit a03dfd4
-rw-r--r--crates/span/src/ast_id.rs42
-rw-r--r--crates/span/src/map.rs33
2 files changed, 49 insertions, 26 deletions
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index 3bf14dea75..da537ba990 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -777,6 +777,48 @@ impl AstIdMap {
}
}
+#[cfg(not(no_salsa_async_drops))]
+impl Drop for AstIdMap {
+ fn drop(&mut self) {
+ let arena = std::mem::take(&mut self.arena);
+ let ptr_map = std::mem::take(&mut self.ptr_map);
+ let id_map = std::mem::take(&mut self.id_map);
+ static AST_ID_MAP_DROP_THREAD: std::sync::OnceLock<
+ std::sync::mpsc::Sender<(
+ Arena<(SyntaxNodePtr, ErasedFileAstId)>,
+ hashbrown::HashTable<ArenaId>,
+ hashbrown::HashTable<ArenaId>,
+ )>,
+ > = std::sync::OnceLock::new();
+ AST_ID_MAP_DROP_THREAD
+ .get_or_init(|| {
+ let (sender, receiver) = std::sync::mpsc::channel::<(
+ Arena<(SyntaxNodePtr, ErasedFileAstId)>,
+ hashbrown::HashTable<ArenaId>,
+ hashbrown::HashTable<ArenaId>,
+ )>();
+ std::thread::Builder::new()
+ .name("AstIdMapDropper".to_owned())
+ .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
+ })
+ .send((arena, ptr_map, id_map))
+ .unwrap();
+ }
+}
+
#[inline]
fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 {
FxBuildHasher.hash_one(ptr)
diff --git a/crates/span/src/map.rs b/crates/span/src/map.rs
index f5c083a9f6..75a1b0029c 100644
--- a/crates/span/src/map.rs
+++ b/crates/span/src/map.rs
@@ -153,26 +153,22 @@ impl SpanMap {
#[cfg(not(no_salsa_async_drops))]
impl Drop for SpanMap {
fn drop(&mut self) {
- struct SendPtr(*mut [()]);
- unsafe impl Send for SendPtr {}
+ let spans = std::mem::take(&mut self.spans);
static SPAN_MAP_DROP_THREAD: std::sync::OnceLock<
- std::sync::mpsc::Sender<(SendPtr, fn(SendPtr))>,
+ std::sync::mpsc::Sender<Vec<(TextSize, Span)>>,
> = std::sync::OnceLock::new();
+
SPAN_MAP_DROP_THREAD
.get_or_init(|| {
- let (sender, receiver) = std::sync::mpsc::channel::<(SendPtr, fn(SendPtr))>();
+ let (sender, receiver) = std::sync::mpsc::channel::<Vec<(TextSize, Span)>>();
std::thread::Builder::new()
.name("SpanMapDropper".to_owned())
.spawn(move || {
loop {
// block on a receive
- if let Ok((b, drop)) = receiver.recv() {
- drop(b);
- }
+ _ = receiver.recv();
// then drain the entire channel
- while let Ok((b, drop)) = receiver.try_recv() {
- drop(b);
- }
+ while let Ok(_) = receiver.try_recv() {}
// and sleep for a bit
std::thread::sleep(std::time::Duration::from_millis(100));
}
@@ -182,22 +178,7 @@ impl Drop for SpanMap {
.unwrap();
sender
})
- .send((
- unsafe {
- SendPtr(std::mem::transmute::<*mut [(TextSize, Span)], *mut [()]>(Box::<
- [(TextSize, Span)],
- >::into_raw(
- std::mem::take(&mut self.spans).into_boxed_slice(),
- )))
- },
- |b: SendPtr| {
- _ = unsafe {
- Box::from_raw(std::mem::transmute::<*mut [()], *mut [(TextSize, Span)]>(
- b.0,
- ))
- }
- },
- ))
+ .send(spans)
.unwrap();
}
}