Skip to content

Commit ce4af66

Browse files
committed
Drop unnecessary locking in Lru::for_each_evicted
1 parent 17c4212 commit ce4af66

File tree

3 files changed

+46
-30
lines changed

3 files changed

+46
-30
lines changed

Diff for: src/function.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,13 @@ where
231231
}
232232

233233
fn reset_for_new_revision(&mut self, table: &mut Table) {
234-
self.lru
235-
.for_each_evicted(|evict| self.evict_value_from_memo_for(table.memos_mut(evict)));
234+
self.lru.for_each_evicted(|evict| {
235+
Self::evict_value_from_memo_for(
236+
table.memos_mut(evict),
237+
self.memo_ingredient_index,
238+
&self.delete,
239+
)
240+
});
236241
}
237242

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

Diff for: src/function/lru.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl Lru {
2828
self.capacity.store(capacity, Ordering::Relaxed);
2929
}
3030

31-
pub(super) fn for_each_evicted(&self, mut cb: impl FnMut(Id)) {
32-
let mut set = self.set.lock();
31+
pub(super) fn for_each_evicted(&mut self, mut cb: impl FnMut(Id)) {
32+
let set = self.set.get_mut();
3333
// Relaxed should be fine, we don't need to synchronize on this.
3434
let cap = self.capacity.load(Ordering::Relaxed);
3535
if set.len() <= cap || cap == 0 {

Diff for: src/function/memo.rs

+37-26
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use std::mem::ManuallyDrop;
55
use std::sync::Arc;
66

77
use crate::accumulator::accumulated_map::InputAccumulatedValues;
8+
use crate::plumbing::MemoDropSender;
89
use crate::revision::AtomicRevision;
910
use crate::table::memo::MemoTable;
11+
use crate::zalsa::MemoIngredientIndex;
1012
use crate::zalsa_local::QueryOrigin;
1113
use crate::{
1214
key::DatabaseKeyIndex, zalsa::Zalsa, zalsa_local::QueryRevisions, Event, EventKind, Id,
@@ -67,7 +69,11 @@ impl<C: Configuration> IngredientImpl<C> {
6769
/// Evicts the existing memo for the given key, replacing it
6870
/// with an equivalent memo that has no value. If the memo is untracked, BaseInput,
6971
/// or has values assigned as output of another query, this has no effect.
70-
pub(super) fn evict_value_from_memo_for(&self, table: &mut MemoTable) {
72+
pub(super) fn evict_value_from_memo_for(
73+
table: &mut MemoTable,
74+
memo_ingredient_index: MemoIngredientIndex,
75+
memo_drop: &MemoDropSender,
76+
) {
7177
let map = |memo: ArcMemo<'static, C>| -> ArcMemo<'static, C> {
7278
match &memo.revisions.origin {
7379
QueryOrigin::Assigned(_)
@@ -81,37 +87,17 @@ impl<C: Configuration> IngredientImpl<C> {
8187
}
8288
QueryOrigin::Derived(_) => {
8389
// Note that we cannot use `Arc::get_mut` here as the use of `ArcSwap` makes it
84-
// impossible to get unique access to the interior Arc
85-
// QueryRevisions: !Clone to discourage cloning, we need it here though
86-
let &QueryRevisions {
87-
changed_at,
88-
durability,
89-
ref origin,
90-
ref tracked_struct_ids,
91-
ref accumulated,
92-
ref accumulated_inputs,
93-
} = &memo.revisions;
94-
// Re-assemble the memo but with the value set to `None`
95-
Arc::new(Memo::new(
96-
None,
97-
memo.verified_at.load(),
98-
QueryRevisions {
99-
changed_at,
100-
durability,
101-
origin: origin.clone(),
102-
tracked_struct_ids: tracked_struct_ids.clone(),
103-
accumulated: accumulated.clone(),
104-
accumulated_inputs: accumulated_inputs.clone(),
105-
},
106-
))
90+
// impossible to get unique access to the interior Arc so we need to construct
91+
// a new allocation
92+
Arc::new(memo.without_value())
10793
}
10894
}
10995
};
11096
// SAFETY: We queue the old value for deletion, delaying its drop until the next revision
11197
// bump.
112-
let old_memo = unsafe { table.map_memo(self.memo_ingredient_index, map) };
98+
let old_memo = unsafe { table.map_memo(memo_ingredient_index, map) };
11399
if let Some(old_memo) = old_memo {
114-
self.delete.delay(ManuallyDrop::into_inner(old_memo));
100+
memo_drop.delay(ManuallyDrop::into_inner(old_memo));
115101
}
116102
}
117103
}
@@ -142,6 +128,31 @@ impl<V> Memo<V> {
142128
revisions,
143129
}
144130
}
131+
132+
pub(super) fn without_value(&self) -> Self {
133+
let &QueryRevisions {
134+
changed_at,
135+
durability,
136+
ref origin,
137+
ref tracked_struct_ids,
138+
ref accumulated,
139+
ref accumulated_inputs,
140+
} = &self.revisions;
141+
// Re-assemble the memo but with the value set to `None`
142+
Memo::new(
143+
None,
144+
self.verified_at.load(),
145+
QueryRevisions {
146+
changed_at,
147+
durability,
148+
origin: origin.clone(),
149+
tracked_struct_ids: tracked_struct_ids.clone(),
150+
accumulated: accumulated.clone(),
151+
accumulated_inputs: accumulated_inputs.clone(),
152+
},
153+
)
154+
}
155+
145156
/// True if this memo is known not to have changed based on its durability.
146157
pub(super) fn check_durability(&self, zalsa: &Zalsa) -> bool {
147158
let last_changed = zalsa.last_changed_revision(self.revisions.durability);

0 commit comments

Comments
 (0)