perf: Reduce memory usage of salsa slots by 8 bytes

This commit is contained in:
Lukas Wirth 2024-07-19 17:34:48 +02:00
parent 546eb6b530
commit 4691ca97f1
3 changed files with 28 additions and 35 deletions

View file

@ -6,7 +6,6 @@ use crate::lru::LruNode;
use crate::plumbing::{DatabaseOps, QueryFunction};
use crate::revision::Revision;
use crate::runtime::local_state::ActiveQueryGuard;
use crate::runtime::local_state::QueryInputs;
use crate::runtime::local_state::QueryRevisions;
use crate::runtime::Runtime;
use crate::runtime::RuntimeId;
@ -28,8 +27,8 @@ where
key_index: u32,
group_index: u16,
state: RwLock<QueryState<Q>>,
policy: PhantomData<MP>,
lru_index: LruIndex,
policy: PhantomData<MP>,
}
/// Defines the "current state" of query's memoized results.
@ -430,7 +429,8 @@ where
tracing::debug!("Slot::invalidate(new_revision = {:?})", new_revision);
match &mut *self.state.write() {
QueryState::Memoized(memo) => {
memo.revisions.inputs = QueryInputs::Untracked;
memo.revisions.untracked = true;
memo.revisions.inputs = None;
memo.revisions.changed_at = new_revision;
Some(memo.revisions.durability)
}
@ -746,11 +746,8 @@ where
match &self.revisions.inputs {
// We can't validate values that had untracked inputs; just have to
// re-execute.
QueryInputs::Untracked => {
return false;
}
QueryInputs::NoInputs => {}
None if self.revisions.untracked => return false,
None => {}
// Check whether any of our inputs changed since the
// **last point where we were verified** (not since we
@ -761,7 +758,7 @@ where
// R1. But our *verification* date will be R2, and we
// are only interested in finding out whether the
// input changed *again*.
QueryInputs::Tracked { inputs } => {
Some(inputs) => {
let changed_input =
inputs.slice.iter().find(|&&input| db.maybe_changed_after(input, verified_at));
if let Some(input) = changed_input {
@ -793,7 +790,7 @@ where
}
fn has_untracked_input(&self) -> bool {
matches!(self.revisions.inputs, QueryInputs::Untracked)
self.revisions.untracked
}
}

View file

@ -18,7 +18,7 @@ use dependency_graph::DependencyGraph;
pub(crate) mod local_state;
use local_state::LocalState;
use self::local_state::{ActiveQueryGuard, QueryInputs, QueryRevisions};
use self::local_state::{ActiveQueryGuard, QueryRevisions};
/// The salsa runtime stores the storage for all queries as well as
/// tracking the query stack and dependencies between cycles.
@ -558,21 +558,25 @@ impl ActiveQuery {
}
pub(crate) fn revisions(&self) -> QueryRevisions {
let inputs = match &self.dependencies {
None => QueryInputs::Untracked,
let (inputs, untracked) = match &self.dependencies {
None => (None, true),
Some(dependencies) => {
Some(dependencies) => (
if dependencies.is_empty() {
QueryInputs::NoInputs
None
} else {
QueryInputs::Tracked {
inputs: ThinArc::from_header_and_iter((), dependencies.iter().copied()),
}
}
}
Some(ThinArc::from_header_and_iter((), dependencies.iter().copied()))
},
false,
),
};
QueryRevisions { changed_at: self.changed_at, inputs, durability: self.durability }
QueryRevisions {
changed_at: self.changed_at,
inputs,
untracked,
durability: self.durability,
}
}
/// Adds any dependencies from `other` into `self`.

View file

@ -34,21 +34,13 @@ pub(crate) struct QueryRevisions {
/// Minimum durability of the inputs to this query.
pub(crate) durability: Durability,
/// Whether the input is untracked.
/// Invariant: if `untracked`, `inputs` is `None`.
/// Why is this encoded like this and not a proper enum? Struct size, this saves us 8 bytes.
pub(crate) untracked: bool,
/// The inputs that went into our query, if we are tracking them.
pub(crate) inputs: QueryInputs,
}
/// Every input.
#[derive(Debug, Clone)]
pub(crate) enum QueryInputs {
/// Non-empty set of inputs, fully known
Tracked { inputs: ThinArc<(), DatabaseKeyIndex> },
/// Empty set of inputs, fully known.
NoInputs,
/// Unknown quantity of inputs
Untracked,
pub(crate) inputs: Option<ThinArc<(), DatabaseKeyIndex>>,
}
impl Default for LocalState {