Skip to content

Commit 0317cd1

Browse files
committed
Move memo dropping off to another thread
1 parent b740ae4 commit 0317cd1

File tree

16 files changed

+278
-113
lines changed

16 files changed

+278
-113
lines changed

Diff for: components/salsa-macro-rules/src/setup_tracked_fn.rs

+2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ macro_rules! setup_tracked_fn {
210210
&self,
211211
aux: &dyn $zalsa::JarAux,
212212
first_index: $zalsa::IngredientIndex,
213+
memo_drop_sender: $zalsa::MemoDropSender,
213214
) -> Vec<Box<dyn $zalsa::Ingredient>> {
214215
let struct_index = $zalsa::macro_if! {
215216
if $needs_interner {
@@ -226,6 +227,7 @@ macro_rules! setup_tracked_fn {
226227
struct_index,
227228
first_index,
228229
aux,
230+
memo_drop_sender
229231
);
230232
$zalsa::macro_if! {
231233
if $has_lru {

Diff for: src/accumulator.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use accumulated::AnyAccumulated;
1212
use crate::{
1313
cycle::CycleRecoveryStrategy,
1414
ingredient::{fmt_index, Ingredient, Jar, MaybeChangedAfter},
15-
plumbing::JarAux,
15+
plumbing::{JarAux, MemoDropSender},
1616
table::Table,
1717
zalsa::IngredientIndex,
1818
zalsa_local::QueryOrigin,
@@ -50,6 +50,7 @@ impl<A: Accumulator> Jar for JarImpl<A> {
5050
&self,
5151
_aux: &dyn JarAux,
5252
first_index: IngredientIndex,
53+
_: MemoDropSender,
5354
) -> Vec<Box<dyn Ingredient>> {
5455
vec![Box::new(<IngredientImpl<A>>::new(first_index))]
5556
}

Diff for: src/exclusive.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/// `std::sync::Exclusive`
2+
pub struct Exclusive<T: ?Sized> {
3+
inner: T,
4+
}
5+
6+
unsafe impl<T> Sync for Exclusive<T> {}
7+
8+
impl<T> Exclusive<T> {
9+
pub fn new(inner: T) -> Self {
10+
Self { inner }
11+
}
12+
pub fn get_mut(&mut self) -> &mut T {
13+
&mut self.inner
14+
}
15+
}

Diff for: src/function.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,16 @@ use crate::{
88
key::DatabaseKeyIndex,
99
plumbing::JarAux,
1010
salsa_struct::SalsaStructInDb,
11-
table::Table,
11+
table::{memo::MemoDropSender, Table},
1212
zalsa::{IngredientIndex, MemoIngredientIndex, Zalsa},
1313
zalsa_local::QueryOrigin,
1414
Cycle, Database, Id, Revision,
1515
};
1616

17-
use self::delete::DeletedEntries;
18-
1917
use super::ingredient::Ingredient;
2018

2119
mod accumulated;
2220
mod backdate;
23-
mod delete;
2421
mod diff_outputs;
2522
mod execute;
2623
mod fetch;
@@ -117,7 +114,7 @@ pub struct IngredientImpl<C: Configuration> {
117114
/// current revision: you would be right, but we are being defensive, because
118115
/// we don't know that we can trust the database to give us the same runtime
119116
/// everytime and so forth.
120-
deleted_entries: DeletedEntries<C>,
117+
delete: MemoDropSender,
121118
}
122119

123120
/// True if `old_value == new_value`. Invoked by the generated
@@ -131,12 +128,17 @@ impl<C> IngredientImpl<C>
131128
where
132129
C: Configuration,
133130
{
134-
pub fn new(struct_index: IngredientIndex, index: IngredientIndex, aux: &dyn JarAux) -> Self {
131+
pub fn new(
132+
struct_index: IngredientIndex,
133+
index: IngredientIndex,
134+
aux: &dyn JarAux,
135+
delete: MemoDropSender,
136+
) -> Self {
135137
Self {
136138
index,
137139
memo_ingredient_index: aux.next_memo_ingredient_index(struct_index, index),
138140
lru: Default::default(),
139-
deleted_entries: Default::default(),
141+
delete,
140142
}
141143
}
142144

@@ -175,13 +177,7 @@ where
175177
// Unsafety conditions: memo must be in the map (it's not yet, but it will be by the time this
176178
// value is returned) and anything removed from map is added to deleted entries (ensured elsewhere).
177179
let db_memo = unsafe { self.extend_memo_lifetime(&memo) };
178-
// Safety: We delay the drop of `old_value` until a new revision starts which ensures no
179-
// references will exist for the memo contents.
180-
if let Some(old_value) = unsafe { self.insert_memo_into_table_for(zalsa, id, memo) } {
181-
// In case there is a reference to the old memo out there, we have to store it
182-
// in the deleted entries. This will get cleared when a new revision starts.
183-
self.deleted_entries.push(old_value);
184-
}
180+
self.insert_memo_into_table_for(zalsa, id, memo);
185181
db_memo
186182
}
187183
}
@@ -238,9 +234,11 @@ where
238234
}
239235

240236
fn reset_for_new_revision(&mut self, table: &mut Table) {
241-
std::mem::take(&mut self.deleted_entries);
242-
self.lru
243-
.to_be_evicted(|evict| self.evict_value_from_memo_for(table.memos_mut(evict)));
237+
self.lru.to_be_evicted(|evict| {
238+
if let Some(memo) = self.evict_value_from_memo_for(table.memos_mut(evict)) {
239+
self.delete.delay(memo);
240+
}
241+
});
244242
}
245243

246244
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {

Diff for: src/function/delete.rs

-25
This file was deleted.

Diff for: src/function/lru.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub trait LruChoice: sealed::Sealed + Default {
1717
fn to_be_evicted(&self, cb: impl FnMut(Id));
1818
/// Sets the capacity of the LRU.
1919
fn set_capacity(&self, capacity: usize);
20-
fn if_enabled(f: impl FnOnce());
20+
fn if_enabled<T>(f: impl FnOnce() -> T) -> Option<T>;
2121

2222
fn evicted<T>() -> Self::LruCtor<T>
2323
where
@@ -53,7 +53,9 @@ impl LruChoice for NoLru {
5353
fn record_use(&self, _: Id) {}
5454
fn to_be_evicted(&self, _: impl FnMut(Id)) {}
5555
fn set_capacity(&self, _: usize) {}
56-
fn if_enabled(_: impl FnOnce()) {}
56+
fn if_enabled<T>(_: impl FnOnce() -> T) -> Option<T> {
57+
None
58+
}
5759

5860
fn evicted<T>() -> Self::LruCtor<T>
5961
where
@@ -124,8 +126,9 @@ impl LruChoice for Lru {
124126
*self.set.lock() = FxLinkedHashSet::default();
125127
}
126128
}
127-
fn if_enabled(f: impl FnOnce()) {
128-
f();
129+
130+
fn if_enabled<T>(f: impl FnOnce() -> T) -> Option<T> {
131+
Some(f())
129132
}
130133

131134
fn evicted<T>() -> Self::LruCtor<T>

Diff for: src/function/memo.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,24 @@ impl<C: Configuration> IngredientImpl<C> {
3737
}
3838

3939
/// Inserts the memo for the given key; (atomically) overwrites and returns any previously existing memo
40-
///
41-
/// # Safety
42-
///
43-
/// The caller needs to make sure to not drop the returned value until no more references into
44-
/// the database exist as there may be outstanding borrows into the `Arc` contents.
45-
pub(super) unsafe fn insert_memo_into_table_for<'db>(
40+
pub(super) fn insert_memo_into_table_for<'db>(
4641
&'db self,
4742
zalsa: &'db Zalsa,
4843
id: Id,
4944
memo: ArcMemo<'db, C>,
50-
) -> Option<ArcMemo<'db, C>> {
45+
) {
5146
let static_memo = unsafe { self.to_static(memo) };
52-
let old_static_memo = zalsa
53-
.memo_table_for(id)
54-
.insert(self.memo_ingredient_index, static_memo)?;
55-
unsafe { Some(self.to_self(old_static_memo)) }
47+
// SAFETY: We delay the deletion of the old memo until the next revision starts.
48+
if let Some(old_static_memo) = unsafe {
49+
zalsa
50+
.memo_table_for(id)
51+
.insert(self.memo_ingredient_index, static_memo)
52+
} {
53+
// In case there is a reference to the old memo out there, we have to delay its
54+
// deletion.
55+
// This will get cleared when a new revision starts.
56+
self.delete.delay(old_static_memo);
57+
}
5658
}
5759

5860
/// Loads the current memo for `key_index`. This does not hold any sort of
@@ -70,7 +72,10 @@ impl<C: Configuration> IngredientImpl<C> {
7072
/// Evicts the existing memo for the given key, replacing it
7173
/// with an equivalent memo that has no value. If the memo is untracked, BaseInput,
7274
/// or has values assigned as output of another query, this has no effect.
73-
pub(super) fn evict_value_from_memo_for(&self, table: &mut MemoTable) {
75+
pub(super) fn evict_value_from_memo_for(
76+
&self,
77+
table: &mut MemoTable,
78+
) -> Option<ArcMemo<'static, C>> {
7479
C::Lru::if_enabled(|| {
7580
table.map_memo::<MemoConfigured<'_, C>>(self.memo_ingredient_index, |memo| {
7681
match &memo.revisions.origin {
@@ -110,8 +115,9 @@ impl<C: Configuration> IngredientImpl<C> {
110115
))
111116
}
112117
}
113-
});
118+
})
114119
})
120+
.flatten()
115121
}
116122
}
117123

Diff for: src/ingredient.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66
use crate::{
77
accumulator::accumulated_map::{AccumulatedMap, InputAccumulatedValues},
88
cycle::CycleRecoveryStrategy,
9+
plumbing::MemoDropSender,
910
table::Table,
1011
zalsa::{IngredientIndex, MemoIngredientIndex},
1112
zalsa_local::QueryOrigin,
@@ -23,6 +24,7 @@ pub trait Jar: Any {
2324
&self,
2425
aux: &dyn JarAux,
2526
first_index: IngredientIndex,
27+
memo_drop_sender: MemoDropSender,
2628
) -> Vec<Box<dyn Ingredient>>;
2729

2830
/// If this jar's first ingredient is a salsa struct, return its `TypeId`

Diff for: src/input.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
ingredient::{fmt_index, Ingredient, MaybeChangedAfter},
1818
input::singleton::{Singleton, SingletonChoice},
1919
key::{DatabaseKeyIndex, InputDependencyIndex},
20-
plumbing::{Jar, JarAux, Stamp},
20+
plumbing::{Jar, JarAux, MemoDropSender, Stamp},
2121
table::{memo::MemoTable, sync::SyncTable, Slot, Table},
2222
zalsa::{IngredientIndex, Zalsa},
2323
zalsa_local::QueryOrigin,
@@ -58,6 +58,7 @@ impl<C: Configuration> Jar for JarImpl<C> {
5858
&self,
5959
_aux: &dyn JarAux,
6060
struct_index: crate::zalsa::IngredientIndex,
61+
_: MemoDropSender,
6162
) -> Vec<Box<dyn Ingredient>> {
6263
let struct_ingredient: IngredientImpl<C> = IngredientImpl::new(struct_index);
6364

Diff for: src/interned.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::accumulator::accumulated_map::InputAccumulatedValues;
44
use crate::durability::Durability;
55
use crate::ingredient::{fmt_index, MaybeChangedAfter};
66
use crate::key::InputDependencyIndex;
7-
use crate::plumbing::{Jar, JarAux};
7+
use crate::plumbing::{Jar, JarAux, MemoDropSender};
88
use crate::table::memo::MemoTable;
99
use crate::table::sync::SyncTable;
1010
use crate::table::{Slot, Table};
@@ -92,6 +92,7 @@ impl<C: Configuration> Jar for JarImpl<C> {
9292
&self,
9393
_aux: &dyn JarAux,
9494
first_index: IngredientIndex,
95+
_: MemoDropSender,
9596
) -> Vec<Box<dyn Ingredient>> {
9697
vec![Box::new(IngredientImpl::<C>::new(first_index)) as _]
9798
}

Diff for: src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod database;
88
mod database_impl;
99
mod durability;
1010
mod event;
11+
mod exclusive;
1112
mod function;
1213
mod hash;
1314
mod id;
@@ -91,6 +92,7 @@ pub mod plumbing {
9192
pub use crate::salsa_struct::SalsaStructInDb;
9293
pub use crate::storage::HasStorage;
9394
pub use crate::storage::Storage;
95+
pub use crate::table::memo::MemoDropSender;
9496
pub use crate::tracked_struct::TrackedStructInDb;
9597
pub use crate::update::always_update;
9698
pub use crate::update::helper::Dispatch as UpdateDispatch;

0 commit comments

Comments
 (0)