Skip to content

Commit

Permalink
Reduce memory usage by deduplicating type information
Browse files Browse the repository at this point in the history
We were storing the type information, 3 words wide, for each memo in each slot, while it is always constant wrt. the ingredient (different slots of the same ingredients will always have the same memos in the same order). This introduces some more unsafety, and the result wasn't as fast so I also had to use some lock-free structures, but the result is worth it: this shaves off 230mb from rust-analyzer with new Salsa.
  • Loading branch information
ChayimFriedman2 committed Jan 31, 2025
1 parent d32b3c1 commit e92d921
Show file tree
Hide file tree
Showing 12 changed files with 380 additions and 165 deletions.
8 changes: 8 additions & 0 deletions src/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
any::Any,
fmt::{self, Debug},
marker::PhantomData,
sync::Arc,
};

use accumulated::Accumulated;
Expand All @@ -13,6 +14,7 @@ use crate::{
cycle::CycleRecoveryStrategy,
ingredient::{fmt_index, Ingredient, Jar, MaybeChangedAfter},
plumbing::JarAux,
table::memo::MemoTableTypes,
zalsa::IngredientIndex,
zalsa_local::QueryOrigin,
Database, DatabaseKeyIndex, Id, Revision,
Expand Down Expand Up @@ -60,6 +62,7 @@ impl<A: Accumulator> Jar for JarImpl<A> {

pub struct IngredientImpl<A: Accumulator> {
index: IngredientIndex,
memo_table_types: Arc<MemoTableTypes>,
phantom: PhantomData<Accumulated<A>>,
}

Expand All @@ -79,6 +82,7 @@ impl<A: Accumulator> IngredientImpl<A> {
pub fn new(index: IngredientIndex) -> Self {
Self {
index,
memo_table_types: Arc::new(MemoTableTypes::default()),
phantom: PhantomData,
}
}
Expand Down Expand Up @@ -148,6 +152,10 @@ impl<A: Accumulator> Ingredient for IngredientImpl<A> {
fn debug_name(&self) -> &'static str {
A::DEBUG_NAME
}

fn memo_table_types(&self) -> Arc<MemoTableTypes> {
self.memo_table_types.clone()
}
}

impl<A> std::fmt::Debug for IngredientImpl<A>
Expand Down
9 changes: 9 additions & 0 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
key::DatabaseKeyIndex,
plumbing::JarAux,
salsa_struct::SalsaStructInDb,
table::memo::MemoTableTypes,
zalsa::{IngredientIndex, MemoIngredientIndex, Zalsa},
zalsa_local::QueryOrigin,
Cycle, Database, Id, Revision,
Expand Down Expand Up @@ -113,6 +114,9 @@ pub struct IngredientImpl<C: Configuration> {
/// we don't know that we can trust the database to give us the same runtime
/// everytime and so forth.
deleted_entries: DeletedEntries<C>,

/// This is empty, but we need this for the trait and it doesn't consume a lot of memory anyway.
_memo_table_types: Arc<MemoTableTypes>,
}

/// True if `old_value == new_value`. Invoked by the generated
Expand All @@ -132,6 +136,7 @@ where
memo_ingredient_index: aux.next_memo_ingredient_index(struct_index, index),
lru: Default::default(),
deleted_entries: Default::default(),
_memo_table_types: Arc::new(MemoTableTypes::default()),
}
}

Expand Down Expand Up @@ -243,6 +248,10 @@ where
C::DEBUG_NAME
}

fn memo_table_types(&self) -> Arc<MemoTableTypes> {
self._memo_table_types.clone()
}

fn accumulated<'db>(
&'db self,
db: &'db dyn Database,
Expand Down
4 changes: 4 additions & 0 deletions src/ingredient.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::{
any::{Any, TypeId},
fmt,
sync::Arc,
};

use crate::{
accumulator::accumulated_map::{AccumulatedMap, InputAccumulatedValues},
cycle::CycleRecoveryStrategy,
table::memo::MemoTableTypes,
zalsa::{IngredientIndex, MemoIngredientIndex},
zalsa_local::QueryOrigin,
Database, DatabaseKeyIndex, Id,
Expand Down Expand Up @@ -124,6 +126,8 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
/// [`IngredientRequiresReset::RESET_ON_NEW_REVISION`] to true.
fn reset_for_new_revision(&mut self);

fn memo_table_types(&self) -> Arc<MemoTableTypes>;

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

Expand Down
34 changes: 27 additions & 7 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{
any::{Any, TypeId},
fmt,
ops::DerefMut,
sync::Arc,
};

pub mod input_field;
Expand All @@ -18,7 +19,11 @@ use crate::{
input::singleton::{Singleton, SingletonChoice},
key::{DatabaseKeyIndex, InputDependencyIndex},
plumbing::{Jar, JarAux, Stamp},
table::{memo::MemoTable, sync::SyncTable, Slot, Table},
table::{
memo::{MemoTable, MemoTableTypes},
sync::SyncTable,
Slot, Table,
},
zalsa::{IngredientIndex, Zalsa},
zalsa_local::QueryOrigin,
Database, Durability, Id, Revision, Runtime,
Expand Down Expand Up @@ -76,6 +81,7 @@ impl<C: Configuration> Jar for JarImpl<C> {
pub struct IngredientImpl<C: Configuration> {
ingredient_index: IngredientIndex,
singleton: C::Singleton,
memo_table_types: Arc<MemoTableTypes>,
_phantom: std::marker::PhantomData<C::Struct>,
}

Expand All @@ -84,6 +90,7 @@ impl<C: Configuration> IngredientImpl<C> {
Self {
ingredient_index: index,
singleton: Default::default(),
memo_table_types: Arc::new(MemoTableTypes::default()),
_phantom: std::marker::PhantomData,
}
}
Expand All @@ -107,12 +114,17 @@ impl<C: Configuration> IngredientImpl<C> {
let (zalsa, zalsa_local) = db.zalsas();

let id = self.singleton.with_lock(|| {
zalsa_local.allocate(zalsa.table(), self.ingredient_index, |_| Value::<C> {
fields,
stamps,
memos: Default::default(),
syncs: Default::default(),
})
zalsa_local.allocate(
zalsa,
zalsa.table(),
self.ingredient_index,
|_| Value::<C> {
fields,
stamps,
memos: Default::default(),
syncs: Default::default(),
},
)
});

FromId::from_id(id)
Expand Down Expand Up @@ -257,6 +269,10 @@ impl<C: Configuration> Ingredient for IngredientImpl<C> {
fn debug_name(&self) -> &'static str {
C::DEBUG_NAME
}

fn memo_table_types(&self) -> Arc<MemoTableTypes> {
self.memo_table_types.clone()
}
}

impl<C: Configuration> std::fmt::Debug for IngredientImpl<C> {
Expand Down Expand Up @@ -301,4 +317,8 @@ where
unsafe fn syncs(&self, _current_revision: Revision) -> &SyncTable {
&self.syncs
}

unsafe fn drop_memos(&mut self, types: &MemoTableTypes) {
self.memos.drop(types);
}
}
9 changes: 8 additions & 1 deletion src/input/input_field.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::cycle::CycleRecoveryStrategy;
use crate::ingredient::{fmt_index, Ingredient, MaybeChangedAfter};
use crate::input::Configuration;
use crate::input::{Configuration, MemoTableTypes};
use crate::zalsa::IngredientIndex;
use crate::zalsa_local::QueryOrigin;
use crate::{Database, DatabaseKeyIndex, Id, Revision};
use std::fmt;
use std::marker::PhantomData;
use std::sync::Arc;

use super::{IngredientImpl, Value};

Expand All @@ -21,6 +22,7 @@ use super::{IngredientImpl, Value};
pub struct FieldIngredientImpl<C: Configuration> {
index: IngredientIndex,
field_index: usize,
memo_table_types: Arc<MemoTableTypes>,
phantom: PhantomData<fn() -> Value<C>>,
}

Expand All @@ -32,6 +34,7 @@ where
Self {
index: struct_index.successor(field_index),
field_index,
memo_table_types: Arc::new(MemoTableTypes::default()),
phantom: PhantomData,
}
}
Expand Down Expand Up @@ -96,6 +99,10 @@ where
fn debug_name(&self) -> &'static str {
C::FIELD_DEBUG_NAMES[self.field_index]
}

fn memo_table_types(&self) -> Arc<MemoTableTypes> {
self.memo_table_types.clone()
}
}

impl<C> std::fmt::Debug for FieldIngredientImpl<C>
Expand Down
25 changes: 19 additions & 6 deletions src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::durability::Durability;
use crate::ingredient::{fmt_index, MaybeChangedAfter};
use crate::key::InputDependencyIndex;
use crate::plumbing::{Jar, JarAux};
use crate::table::memo::MemoTable;
use crate::table::memo::{MemoTable, MemoTableTypes};
use crate::table::sync::SyncTable;
use crate::table::Slot;
use crate::zalsa::IngredientIndex;
Expand All @@ -16,6 +16,7 @@ use std::fmt;
use std::hash::{BuildHasher, Hash, Hasher};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use super::hash::FxDashMap;
use super::ingredient::Ingredient;
Expand Down Expand Up @@ -67,6 +68,8 @@ pub struct IngredientImpl<C: Configuration> {
/// but that will make anything dependent on those entries dirty and in need
/// of being recomputed.
reset_at: Revision,

memo_table_types: Arc<MemoTableTypes>,
}

/// Struct storing the interned fields.
Expand Down Expand Up @@ -110,6 +113,7 @@ where
ingredient_index,
key_map: Default::default(),
reset_at: Revision::start(),
memo_table_types: Arc::new(MemoTableTypes::default()),
}
}

Expand Down Expand Up @@ -202,11 +206,12 @@ where
Err(slot) => {
let zalsa = db.zalsa();
let table = zalsa.table();
let id = zalsa_local.allocate(table, self.ingredient_index, |id| Value::<C> {
data: unsafe { self.to_internal_data(assemble(id, key)) },
memos: Default::default(),
syncs: Default::default(),
});
let id =
zalsa_local.allocate(zalsa, table, self.ingredient_index, |id| Value::<C> {
data: unsafe { self.to_internal_data(assemble(id, key)) },
memos: Default::default(),
syncs: Default::default(),
});
unsafe {
lock.insert_in_slot(
data_hash,
Expand Down Expand Up @@ -313,6 +318,10 @@ where
fn debug_name(&self) -> &'static str {
C::DEBUG_NAME
}

fn memo_table_types(&self) -> Arc<MemoTableTypes> {
self.memo_table_types.clone()
}
}

impl<C> std::fmt::Debug for IngredientImpl<C>
Expand All @@ -337,6 +346,10 @@ where
unsafe fn syncs(&self, _current_revision: Revision) -> &crate::table::sync::SyncTable {
&self.syncs
}

unsafe fn drop_memos(&mut self, types: &MemoTableTypes) {
self.memos.drop(types);
}
}

/// A trait for types that hash and compare like `O`.
Expand Down
Loading

0 comments on commit e92d921

Please sign in to comment.