Skip to content

Commit 5750c84

Browse files
Pack QueryOrigin memory layout (#885)
* pack `QueryOrigin` into 13 bytes * nits Co-authored-by: David Barsky <[email protected]> --------- Co-authored-by: David Barsky <[email protected]>
1 parent 40d7844 commit 5750c84

14 files changed

+293
-113
lines changed

src/active_query.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::key::DatabaseKeyIndex;
1111
use crate::runtime::Stamp;
1212
use crate::sync::atomic::AtomicBool;
1313
use crate::tracked_struct::{Disambiguator, DisambiguatorMap, IdentityHash, IdentityMap};
14-
use crate::zalsa_local::{QueryEdge, QueryEdges, QueryOrigin, QueryRevisions};
14+
use crate::zalsa_local::{QueryEdge, QueryOrigin, QueryRevisions};
1515
use crate::{Accumulator, IngredientIndex, Revision};
1616

1717
#[derive(Debug)]
@@ -193,11 +193,10 @@ impl ActiveQuery {
193193
iteration_count: _,
194194
} = self;
195195

196-
let edges = QueryEdges::new(input_outputs.drain(..));
197196
let origin = if untracked_read {
198-
QueryOrigin::DerivedUntracked(edges)
197+
QueryOrigin::derived_untracked(input_outputs.drain(..))
199198
} else {
200-
QueryOrigin::Derived(edges)
199+
QueryOrigin::derived(input_outputs.drain(..))
201200
};
202201
disambiguator_map.clear();
203202
let accumulated = accumulated

src/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::table::memo::MemoTableTypes;
1717
use crate::table::Table;
1818
use crate::views::DatabaseDownCaster;
1919
use crate::zalsa::{IngredientIndex, MemoIngredientIndex, Zalsa};
20-
use crate::zalsa_local::QueryOrigin;
20+
use crate::zalsa_local::QueryOriginRef;
2121
use crate::{Database, Id, Revision};
2222

2323
mod accumulated;
@@ -268,7 +268,7 @@ where
268268
}
269269
}
270270

271-
fn origin(&self, zalsa: &Zalsa, key: Id) -> Option<QueryOrigin> {
271+
fn origin<'db>(&self, zalsa: &'db Zalsa, key: Id) -> Option<QueryOriginRef<'db>> {
272272
self.origin(zalsa, key)
273273
}
274274

src/function/accumulated.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::accumulator::{self};
33
use crate::function::{Configuration, IngredientImpl};
44
use crate::hash::FxHashSet;
55
use crate::zalsa::ZalsaDatabase;
6-
use crate::zalsa_local::QueryOrigin;
6+
use crate::zalsa_local::QueryOriginRef;
77
use crate::{AsDynDatabase, DatabaseKeyIndex, Id};
88

99
impl<C> IngredientImpl<C>
@@ -73,8 +73,9 @@ where
7373
continue;
7474
};
7575

76-
if let QueryOrigin::Derived(edges) | QueryOrigin::DerivedUntracked(edges) = &origin {
77-
stack.reserve(edges.input_outputs.len());
76+
if let QueryOriginRef::Derived(edges) | QueryOriginRef::DerivedUntracked(edges) = origin
77+
{
78+
stack.reserve(edges.len());
7879
}
7980

8081
stack.extend(

src/function/diff_outputs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ where
2828
let mut old_outputs: FxIndexSet<_> = old_memo
2929
.revisions
3030
.origin
31+
.as_ref()
3132
.outputs()
3233
.map(|a| (a.ingredient_index(), a.key_index().index()))
3334
.collect();
@@ -38,7 +39,7 @@ where
3839

3940
// Iterate over the outputs of the current query
4041
// and remove elements from `old_outputs` when we find them
41-
for new_output in revisions.origin.outputs() {
42+
for new_output in revisions.origin.as_ref().outputs() {
4243
old_outputs.swap_remove(&(
4344
new_output.ingredient_index(),
4445
new_output.key_index().index(),

src/function/inputs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use crate::function::{Configuration, IngredientImpl};
22
use crate::zalsa::Zalsa;
3-
use crate::zalsa_local::QueryOrigin;
3+
use crate::zalsa_local::QueryOriginRef;
44
use crate::Id;
55

66
impl<C> IngredientImpl<C>
77
where
88
C: Configuration,
99
{
10-
pub(super) fn origin(&self, zalsa: &Zalsa, key: Id) -> Option<QueryOrigin> {
10+
pub(super) fn origin<'db>(&self, zalsa: &'db Zalsa, key: Id) -> Option<QueryOriginRef<'db>> {
1111
let memo_ingredient_index = self.memo_ingredient_index(zalsa, key);
1212
self.get_memo_from_table_for(zalsa, key, memo_ingredient_index)
13-
.map(|m| m.revisions.origin.clone())
13+
.map(|m| m.revisions.origin.as_ref())
1414
}
1515
}

src/function/maybe_changed_after.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::key::DatabaseKeyIndex;
77
use crate::plumbing::ZalsaLocal;
88
use crate::sync::atomic::Ordering;
99
use crate::zalsa::{MemoIngredientIndex, Zalsa, ZalsaDatabase};
10-
use crate::zalsa_local::{QueryEdge, QueryOrigin};
10+
use crate::zalsa_local::{QueryEdge, QueryOriginRef};
1111
use crate::{AsDynDatabase as _, Id, Revision};
1212

1313
/// Result of memo validation.
@@ -353,8 +353,8 @@ where
353353
return VerifyResult::unchanged();
354354
}
355355

356-
match &old_memo.revisions.origin {
357-
QueryOrigin::Assigned(_) => {
356+
match old_memo.revisions.origin.as_ref() {
357+
QueryOriginRef::Assigned(_) => {
358358
// If the value was assigned by another query,
359359
// and that query were up-to-date,
360360
// then we would have updated the `verified_at` field already.
@@ -372,15 +372,15 @@ where
372372
// when we hit the cycle. Any dependencies accessed when creating the fixpoint initial
373373
// are tracked by the outer query. Nothing should have changed assuming that the
374374
// fixpoint initial function is deterministic.
375-
QueryOrigin::FixpointInitial => {
375+
QueryOriginRef::FixpointInitial => {
376376
cycle_heads.push_initial(database_key_index);
377377
VerifyResult::unchanged()
378378
}
379-
QueryOrigin::DerivedUntracked(_) => {
379+
QueryOriginRef::DerivedUntracked(_) => {
380380
// Untracked inputs? Have to assume that it changed.
381381
VerifyResult::Changed
382382
}
383-
QueryOrigin::Derived(edges) => {
383+
QueryOriginRef::Derived(edges) => {
384384
let is_provisional = old_memo.may_be_provisional();
385385

386386
// If the value is from the same revision but is still provisional, consider it changed
@@ -398,7 +398,7 @@ where
398398
// they executed. It's possible that if the value of some input I0 is no longer
399399
// valid, then some later input I1 might never have executed at all, so verifying
400400
// it is still up to date is meaningless.
401-
for &edge in edges.input_outputs.iter() {
401+
for &edge in edges {
402402
match edge {
403403
QueryEdge::Input(dependency_index) => {
404404
match dependency_index.maybe_changed_after(

src/function/memo.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::revision::AtomicRevision;
1010
use crate::sync::atomic::Ordering;
1111
use crate::table::memo::MemoTableWithTypesMut;
1212
use crate::zalsa::{MemoIngredientIndex, Zalsa};
13-
use crate::zalsa_local::{QueryOrigin, QueryRevisions};
13+
use crate::zalsa_local::{QueryOriginRef, QueryRevisions};
1414
use crate::{Event, EventKind, Id, Revision};
1515

1616
impl<C: Configuration> IngredientImpl<C> {
@@ -64,16 +64,16 @@ impl<C: Configuration> IngredientImpl<C> {
6464
memo_ingredient_index: MemoIngredientIndex,
6565
) {
6666
let map = |memo: &mut Memo<C::Output<'static>>| {
67-
match &memo.revisions.origin {
68-
QueryOrigin::Assigned(_)
69-
| QueryOrigin::DerivedUntracked(_)
70-
| QueryOrigin::FixpointInitial => {
67+
match memo.revisions.origin.as_ref() {
68+
QueryOriginRef::Assigned(_)
69+
| QueryOriginRef::DerivedUntracked(_)
70+
| QueryOriginRef::FixpointInitial => {
7171
// Careful: Cannot evict memos whose values were
7272
// assigned as output of another query
7373
// or those with untracked inputs
7474
// as their values cannot be reconstructed.
7575
}
76-
QueryOrigin::Derived(_) => {
76+
QueryOriginRef::Derived(_) => {
7777
// Set the memo value to `None`.
7878
memo.value = None;
7979
}
@@ -101,7 +101,7 @@ pub struct Memo<V> {
101101
#[cfg(not(feature = "shuttle"))]
102102
#[cfg(target_pointer_width = "64")]
103103
const _: [(); std::mem::size_of::<Memo<std::num::NonZeroUsize>>()] =
104-
[(); std::mem::size_of::<[usize; 13]>()];
104+
[(); std::mem::size_of::<[usize; 11]>()];
105105

106106
impl<V> Memo<V> {
107107
pub(super) fn new(value: Option<V>, revision_now: Revision, revisions: QueryRevisions) -> Self {
@@ -230,7 +230,7 @@ impl<V> Memo<V> {
230230
zalsa: &Zalsa,
231231
database_key_index: DatabaseKeyIndex,
232232
) {
233-
for output in self.revisions.origin.outputs() {
233+
for output in self.revisions.origin.as_ref().outputs() {
234234
output.mark_validated_output(zalsa, database_key_index);
235235
}
236236
}
@@ -262,7 +262,7 @@ impl<V> Memo<V> {
262262
}
263263

264264
impl<V: Send + Sync + Any> crate::table::memo::Memo for Memo<V> {
265-
fn origin(&self) -> &QueryOrigin {
266-
&self.revisions.origin
265+
fn origin(&self) -> QueryOriginRef<'_> {
266+
self.revisions.origin.as_ref()
267267
}
268268
}

src/function/specify.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::revision::AtomicRevision;
55
use crate::sync::atomic::AtomicBool;
66
use crate::tracked_struct::TrackedStructInDb;
77
use crate::zalsa::{Zalsa, ZalsaDatabase};
8-
use crate::zalsa_local::{QueryOrigin, QueryRevisions};
8+
use crate::zalsa_local::{QueryOrigin, QueryOriginRef, QueryRevisions};
99
use crate::{DatabaseKeyIndex, Id};
1010

1111
impl<C> IngredientImpl<C>
@@ -65,7 +65,7 @@ where
6565
let mut revisions = QueryRevisions {
6666
changed_at: current_deps.changed_at,
6767
durability: current_deps.durability,
68-
origin: QueryOrigin::Assigned(active_query_key),
68+
origin: QueryOrigin::assigned(active_query_key),
6969
tracked_struct_ids: Default::default(),
7070
accumulated: Default::default(),
7171
accumulated_inputs: Default::default(),
@@ -116,8 +116,8 @@ where
116116

117117
// If we are marking this as validated, it must be a value that was
118118
// assigned by `executor`.
119-
match memo.revisions.origin {
120-
QueryOrigin::Assigned(by_query) => assert_eq!(by_query, executor),
119+
match memo.revisions.origin.as_ref() {
120+
QueryOriginRef::Assigned(by_query) => assert_eq!(by_query, executor),
121121
_ => panic!(
122122
"expected a query assigned by `{:?}`, not `{:?}`",
123123
executor, memo.revisions.origin,

src/ingredient.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::sync::Arc;
99
use crate::table::memo::MemoTableTypes;
1010
use crate::table::Table;
1111
use crate::zalsa::{transmute_data_mut_ptr, transmute_data_ptr, IngredientIndex, Zalsa};
12-
use crate::zalsa_local::QueryOrigin;
12+
use crate::zalsa_local::QueryOriginRef;
1313
use crate::{Database, DatabaseKeyIndex, Id, Revision};
1414

1515
/// A "jar" is a group of ingredients that are added atomically.
@@ -150,7 +150,7 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
150150
}
151151

152152
/// What were the inputs (if any) that were used to create the value at `key_index`.
153-
fn origin(&self, zalsa: &Zalsa, key_index: Id) -> Option<QueryOrigin> {
153+
fn origin<'db>(&self, zalsa: &'db Zalsa, key_index: Id) -> Option<QueryOriginRef<'db>> {
154154
let _ = (zalsa, key_index);
155155
unreachable!("only function ingredients have origins")
156156
}

src/memo_ingredient_indices.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl NewMemoIngredientIndices for MemoIngredientIndices {
7777
};
7878
let mut indices = Vec::new();
7979
indices.resize(
80-
last.as_usize() + 1,
80+
(last.as_u32() as usize) + 1,
8181
MemoIngredientIndex::from_usize((u32::MAX - 1) as usize),
8282
);
8383
for &struct_ingredient in &struct_indices.indices {
@@ -88,7 +88,7 @@ impl NewMemoIngredientIndices for MemoIngredientIndices {
8888
let mi = zalsa.next_memo_ingredient_index(struct_ingredient, ingredient);
8989
memo_types.set(mi, &memo_type);
9090

91-
indices[struct_ingredient.as_usize()] = mi;
91+
indices[struct_ingredient.as_u32() as usize] = mi;
9292
}
9393
MemoIngredientIndices {
9494
indices: indices.into_boxed_slice(),
@@ -125,7 +125,7 @@ impl MemoIngredientMap for MemoIngredientIndices {
125125
}
126126
#[inline(always)]
127127
fn get(&self, index: IngredientIndex) -> MemoIngredientIndex {
128-
self.indices[index.as_usize()]
128+
self.indices[index.as_u32() as usize]
129129
}
130130
}
131131

src/table/memo.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use thin_vec::ThinVec;
99

1010
use crate::sync::atomic::{AtomicPtr, Ordering};
1111
use crate::sync::{OnceLock, RwLock};
12-
use crate::{zalsa::MemoIngredientIndex, zalsa_local::QueryOrigin};
12+
use crate::{zalsa::MemoIngredientIndex, zalsa_local::QueryOriginRef};
1313

1414
/// The "memo table" stores the memoized results of tracked function calls.
1515
/// Every tracked function must take a salsa struct as its first argument
@@ -21,7 +21,7 @@ pub(crate) struct MemoTable {
2121

2222
pub trait Memo: Any + Send + Sync {
2323
/// Returns the `origin` of this memo
24-
fn origin(&self) -> &QueryOrigin;
24+
fn origin(&self) -> QueryOriginRef<'_>;
2525
}
2626

2727
/// Data for a memoized entry.
@@ -103,7 +103,7 @@ impl MemoEntryType {
103103
struct DummyMemo {}
104104

105105
impl Memo for DummyMemo {
106-
fn origin(&self) -> &QueryOrigin {
106+
fn origin(&self) -> QueryOriginRef<'_> {
107107
unreachable!("should not get here")
108108
}
109109
}

src/tracked_struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ where
447447
// shouldn't be a problem in general as sufficient bits are reserved for the generation.
448448
let Some(id) = id.next_generation() else {
449449
tracing::info!(
450-
"leaking tracked struct {:?} due to generation oveflow",
450+
"leaking tracked struct {:?} due to generation overflow",
451451
self.database_key_index(id)
452452
);
453453

@@ -547,7 +547,7 @@ where
547547
// the previous slot and allocate a new value.
548548
if id.generation() == u32::MAX {
549549
tracing::info!(
550-
"leaking tracked struct {:?} due to generation oveflow",
550+
"leaking tracked struct {:?} due to generation overflow",
551551
self.database_key_index(id)
552552
);
553553

src/zalsa.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ impl IngredientIndex {
8383
Self(v as u32)
8484
}
8585

86-
/// Convert the ingredient index back into a usize.
87-
pub(crate) fn as_usize(self) -> usize {
88-
self.0 as usize
86+
/// Convert the ingredient index back into a `u32`.
87+
pub(crate) fn as_u32(self) -> u32 {
88+
self.0
8989
}
9090

9191
pub fn successor(self, index: usize) -> Self {
@@ -202,7 +202,7 @@ impl Zalsa {
202202

203203
#[inline]
204204
pub(crate) fn lookup_ingredient(&self, index: IngredientIndex) -> &dyn Ingredient {
205-
let index = index.as_usize();
205+
let index = index.as_u32() as usize;
206206
self.ingredients_vec
207207
.get(index)
208208
.unwrap_or_else(|| panic!("index `{index}` is uninitialized"))
@@ -214,7 +214,7 @@ impl Zalsa {
214214
struct_ingredient_index: IngredientIndex,
215215
memo_ingredient_index: MemoIngredientIndex,
216216
) -> IngredientIndex {
217-
self.memo_ingredient_indices.read()[struct_ingredient_index.as_usize()]
217+
self.memo_ingredient_indices.read()[struct_ingredient_index.as_u32() as usize]
218218
[memo_ingredient_index.as_usize()]
219219
}
220220

@@ -240,7 +240,7 @@ impl Zalsa {
240240
ingredient_index: IngredientIndex,
241241
) -> MemoIngredientIndex {
242242
let mut memo_ingredients = self.memo_ingredient_indices.write();
243-
let idx = struct_ingredient_index.as_usize();
243+
let idx = struct_ingredient_index.as_u32() as usize;
244244
let memo_ingredients = if let Some(memo_ingredients) = memo_ingredients.get_mut(idx) {
245245
memo_ingredients
246246
} else {
@@ -305,7 +305,7 @@ impl Zalsa {
305305

306306
let actual_index = self.ingredients_vec.push(ingredient);
307307
assert_eq!(
308-
expected_index.as_usize(),
308+
expected_index.as_u32() as usize,
309309
actual_index,
310310
"ingredient `{:?}` was predicted to have index `{:?}` but actually has index `{:?}`",
311311
self.ingredients_vec[actual_index],
@@ -328,7 +328,7 @@ impl Zalsa {
328328
&mut self,
329329
index: IngredientIndex,
330330
) -> (&mut dyn Ingredient, &mut Runtime) {
331-
let index = index.as_usize();
331+
let index = index.as_u32() as usize;
332332
let ingredient = self
333333
.ingredients_vec
334334
.get_mut(index)
@@ -358,7 +358,7 @@ impl Zalsa {
358358
let _span = tracing::debug_span!("new_revision", ?new_revision).entered();
359359

360360
for (_, index) in self.ingredients_requiring_reset.iter() {
361-
let index = index.as_usize();
361+
let index = index.as_u32() as usize;
362362
let ingredient = self
363363
.ingredients_vec
364364
.get_mut(index)
@@ -375,7 +375,7 @@ impl Zalsa {
375375
pub fn evict_lru(&mut self) {
376376
let _span = tracing::debug_span!("evict_lru").entered();
377377
for (_, index) in self.ingredients_requiring_reset.iter() {
378-
let index = index.as_usize();
378+
let index = index.as_u32() as usize;
379379
self.ingredients_vec
380380
.get_mut(index)
381381
.unwrap_or_else(|| panic!("index `{index}` is uninitialized"))

0 commit comments

Comments
 (0)