Skip to content

Commit d22e36a

Browse files
committed
Add `MemoryUsageVisitor
1 parent 2edd783 commit d22e36a

File tree

14 files changed

+310
-257
lines changed

14 files changed

+310
-257
lines changed

components/salsa-macro-rules/src/setup_input_struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ macro_rules! setup_input_struct {
103103
type Durabilities = [$zalsa::Durability; $N];
104104

105105
$(
106-
fn heap_size(value: &Self::Fields) -> Option<usize> {
107-
Some($heap_size_fn(value))
106+
fn heap_size(value: &Self::Fields, visitor: &mut dyn salsa::MemoryUsageVisitor) -> Option<usize> {
107+
Some($heap_size_fn(value, visitor))
108108
}
109109
)?
110110
}

components/salsa-macro-rules/src/setup_interned_struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ macro_rules! setup_interned_struct {
151151
type Struct<'db> = $Struct< $($db_lt_arg)? >;
152152

153153
$(
154-
fn heap_size(value: &Self::Fields<'_>) -> Option<usize> {
155-
Some($heap_size_fn(value))
154+
fn heap_size(value: &Self::Fields<'_>, visitor: &mut dyn salsa::MemoryUsageVisitor) -> Option<usize> {
155+
Some($heap_size_fn(value, visitor))
156156
}
157157
)?
158158
}

components/salsa-macro-rules/src/setup_tracked_fn.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ macro_rules! setup_tracked_fn {
231231
$($values_equal)+
232232

233233
$(
234-
fn heap_size(value: &Self::Output<'_>) -> Option<usize> {
235-
Some($heap_size_fn(value))
234+
fn heap_size(value: &Self::Output<'_>, visitor: &mut dyn salsa::MemoryUsageVisitor) -> Option<usize> {
235+
Some($heap_size_fn(value, visitor))
236236
}
237237
)?
238238

components/salsa-macro-rules/src/setup_tracked_struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ macro_rules! setup_tracked_struct {
190190
}
191191

192192
$(
193-
fn heap_size(value: &Self::Fields<'_>) -> Option<usize> {
194-
Some($heap_size_fn(value))
193+
fn heap_size(value: &Self::Fields<'_>, visitor: &mut dyn salsa::MemoryUsageVisitor) -> Option<usize> {
194+
Some($heap_size_fn(value, visitor))
195195
}
196196
)?
197197
}

src/database.rs

Lines changed: 70 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -138,98 +138,66 @@ impl dyn Database {
138138
}
139139

140140
#[cfg(feature = "salsa_unstable")]
141-
pub use memory_usage::IngredientInfo;
142-
143-
#[cfg(feature = "salsa_unstable")]
144-
pub(crate) use memory_usage::{MemoInfo, SlotInfo};
141+
pub use memory_usage::{MemoMemoryInfo, MemoryUsageVisitor, StructMemoryInfo};
145142

146143
#[cfg(feature = "salsa_unstable")]
147144
mod memory_usage {
148145
use crate::Database;
149-
use hashbrown::HashMap;
150146

151-
impl dyn Database {
152-
/// Returns information about any Salsa structs.
153-
pub fn structs_info(&self) -> Vec<IngredientInfo> {
154-
self.zalsa()
155-
.ingredients()
156-
.filter_map(|ingredient| {
157-
let mut size_of_fields = 0;
158-
let mut size_of_metadata = 0;
159-
let mut instances = 0;
160-
let mut heap_size_of_fields = None;
161-
162-
for slot in ingredient.memory_usage(self)? {
163-
instances += 1;
164-
size_of_fields += slot.size_of_fields;
165-
size_of_metadata += slot.size_of_metadata;
166-
167-
if let Some(slot_heap_size) = slot.heap_size_of_fields {
168-
heap_size_of_fields =
169-
Some(heap_size_of_fields.unwrap_or_default() + slot_heap_size);
170-
}
171-
}
172-
173-
Some(IngredientInfo {
174-
count: instances,
175-
size_of_fields,
176-
size_of_metadata,
177-
heap_size_of_fields,
178-
debug_name: ingredient.debug_name(),
179-
})
180-
})
181-
.collect()
147+
pub trait MemoryUsageVisitor: std::any::Any {
148+
fn visit_tracked_struct(&mut self, info: StructMemoryInfo) {
149+
self.visit_struct(info);
182150
}
183151

184-
/// Returns information about any memoized Salsa queries.
185-
///
186-
/// The returned map holds memory usage information for memoized values of a given query, keyed
187-
/// by the query function name.
188-
pub fn queries_info(&self) -> HashMap<&'static str, IngredientInfo> {
189-
let mut queries = HashMap::new();
190-
191-
for input_ingredient in self.zalsa().ingredients() {
192-
let Some(input_info) = input_ingredient.memory_usage(self) else {
193-
continue;
194-
};
195-
196-
for input in input_info {
197-
for memo in input.memos {
198-
let info = queries.entry(memo.debug_name).or_insert(IngredientInfo {
199-
debug_name: memo.output.debug_name,
200-
..Default::default()
201-
});
202-
203-
info.count += 1;
204-
info.size_of_fields += memo.output.size_of_fields;
205-
info.size_of_metadata += memo.output.size_of_metadata;
206-
207-
if let Some(memo_heap_size) = memo.output.heap_size_of_fields {
208-
info.heap_size_of_fields =
209-
Some(info.heap_size_of_fields.unwrap_or_default() + memo_heap_size);
210-
}
211-
}
212-
}
213-
}
152+
fn visit_memo(&mut self, info: MemoMemoryInfo) {
153+
let _ = info;
154+
}
155+
156+
fn visit_input_struct(&mut self, info: StructMemoryInfo) {
157+
self.visit_struct(info);
158+
}
159+
160+
fn visit_interned_struct(&mut self, info: StructMemoryInfo) {
161+
self.visit_struct(info);
162+
}
163+
164+
fn visit_struct(&mut self, info: StructMemoryInfo) {
165+
let _ = info;
166+
}
214167

215-
queries
168+
fn add_detail(&mut self, name: &'static str, size: usize) {
169+
let (_, _) = (name, size);
216170
}
217171
}
218172

219-
/// Information about instances of a particular Salsa ingredient.
220-
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
221-
pub struct IngredientInfo {
222-
debug_name: &'static str,
223-
count: usize,
224-
size_of_metadata: usize,
225-
size_of_fields: usize,
226-
heap_size_of_fields: Option<usize>,
173+
impl dyn Database {
174+
/// Collects information about the memory usage of salsa structs and query functions.
175+
pub fn memory_usage(&self, visitor: &mut dyn MemoryUsageVisitor) {
176+
for ingredient in self.zalsa().ingredients() {
177+
ingredient.memory_usage(self, visitor);
178+
}
179+
}
180+
}
181+
182+
/// Memory usage information about a particular instance of struct, input, output, or memo.
183+
#[derive(Debug, PartialEq, Eq)]
184+
pub struct MemoMemoryInfo {
185+
pub(crate) query_debug_name: &'static str,
186+
pub(crate) result_debug_name: &'static str,
187+
pub(crate) size_of_metadata: usize,
188+
pub(crate) size_of_fields: usize,
189+
pub(crate) heap_size_of_fields: Option<usize>,
227190
}
228191

229-
impl IngredientInfo {
192+
impl MemoMemoryInfo {
230193
/// Returns the debug name of the ingredient.
231-
pub fn debug_name(&self) -> &'static str {
232-
self.debug_name
194+
pub fn query_debug_name(&self) -> &'static str {
195+
self.query_debug_name
196+
}
197+
198+
/// Returns the debug name of the ingredient.
199+
pub fn result_debug_name(&self) -> &'static str {
200+
self.result_debug_name
233201
}
234202

235203
/// Returns the total stack size of the fields of any instances of this ingredient, in bytes.
@@ -248,25 +216,37 @@ mod memory_usage {
248216
pub fn size_of_metadata(&self) -> usize {
249217
self.size_of_metadata
250218
}
251-
252-
/// Returns the number of instances of this ingredient.
253-
pub fn count(&self) -> usize {
254-
self.count
255-
}
256219
}
257220

258-
/// Memory usage information about a particular instance of struct, input or output.
259-
pub struct SlotInfo {
221+
#[derive(Debug, PartialEq, Eq)]
222+
pub struct StructMemoryInfo {
260223
pub(crate) debug_name: &'static str,
261224
pub(crate) size_of_metadata: usize,
262225
pub(crate) size_of_fields: usize,
263226
pub(crate) heap_size_of_fields: Option<usize>,
264-
pub(crate) memos: Vec<MemoInfo>,
265227
}
266228

267-
/// Memory usage information about a particular memo.
268-
pub struct MemoInfo {
269-
pub(crate) debug_name: &'static str,
270-
pub(crate) output: SlotInfo,
229+
impl StructMemoryInfo {
230+
/// Returns the debug name of the ingredient.
231+
pub fn debug_name(&self) -> &'static str {
232+
self.debug_name
233+
}
234+
235+
/// Returns the total stack size of the fields of any instances of this ingredient, in bytes.
236+
pub fn size_of_fields(&self) -> usize {
237+
self.size_of_fields
238+
}
239+
240+
/// Returns the total heap size of the fields of any instances of this ingredient, in bytes.
241+
///
242+
/// Returns `None` if the ingredient doesn't specify a `heap_size` function.
243+
pub fn heap_size_of_fields(&self) -> Option<usize> {
244+
self.heap_size_of_fields
245+
}
246+
247+
/// Returns the total size of Salsa metadata of any instances of this ingredient, in bytes.
248+
pub fn size_of_metadata(&self) -> usize {
249+
self.size_of_metadata
250+
}
271251
}
272252
}

src/function.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ pub trait Configuration: Any {
7474
fn id_to_input(db: &Self::DbView, key: Id) -> Self::Input<'_>;
7575

7676
/// Returns the size of any heap allocations in the output value, in bytes.
77-
fn heap_size(_value: &Self::Output<'_>) -> Option<usize> {
77+
fn heap_size(
78+
_value: &Self::Output<'_>,
79+
_visitor: &mut dyn crate::MemoryUsageVisitor,
80+
) -> Option<usize> {
7881
None
7982
}
8083

src/function/memo.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use crate::sync::atomic::Ordering;
1414
use crate::table::memo::MemoTableWithTypesMut;
1515
use crate::zalsa::{MemoIngredientIndex, Zalsa};
1616
use crate::zalsa_local::{QueryOriginRef, QueryRevisions, ZalsaLocal};
17+
#[cfg(feature = "salsa_unstable")]
18+
use crate::MemoryUsageVisitor;
1719
use crate::{Event, EventKind, Id, Revision};
1820

1921
impl<C: Configuration> IngredientImpl<C> {
@@ -316,24 +318,21 @@ where
316318
}
317319

318320
#[cfg(feature = "salsa_unstable")]
319-
fn memory_usage(&self) -> crate::database::MemoInfo {
321+
fn memory_usage(&self, visitor: &mut dyn MemoryUsageVisitor) {
320322
let size_of = std::mem::size_of::<Memo<C>>() + self.revisions.allocation_size();
321323
let heap_size = if let Some(value) = self.value.as_ref() {
322-
C::heap_size(value)
324+
C::heap_size(value, visitor)
323325
} else {
324326
Some(0)
325327
};
326328

327-
crate::database::MemoInfo {
328-
debug_name: C::DEBUG_NAME,
329-
output: crate::database::SlotInfo {
330-
size_of_metadata: size_of - std::mem::size_of::<C::Output<'static>>(),
331-
debug_name: std::any::type_name::<C::Output<'static>>(),
332-
size_of_fields: std::mem::size_of::<C::Output<'static>>(),
333-
heap_size_of_fields: heap_size,
334-
memos: Vec::new(),
335-
},
336-
}
329+
visitor.visit_memo(crate::database::MemoMemoryInfo {
330+
size_of_metadata: size_of - std::mem::size_of::<C::Output<'static>>(),
331+
query_debug_name: C::DEBUG_NAME,
332+
result_debug_name: std::any::type_name::<C::Output<'static>>(),
333+
size_of_fields: std::mem::size_of::<C::Output<'static>>(),
334+
heap_size_of_fields: heap_size,
335+
})
337336
}
338337
}
339338

src/ingredient.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use crate::table::memo::MemoTableTypes;
1212
use crate::table::Table;
1313
use crate::zalsa::{transmute_data_mut_ptr, transmute_data_ptr, IngredientIndex, Zalsa};
1414
use crate::zalsa_local::QueryOriginRef;
15+
#[cfg(feature = "salsa_unstable")]
16+
use crate::MemoryUsageVisitor;
1517
use crate::{Database, DatabaseKeyIndex, Id, Revision};
1618

1719
/// A "jar" is a group of ingredients that are added atomically.
@@ -171,8 +173,8 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
171173
/// Returns memory usage information about any instances of the ingredient,
172174
/// if applicable.
173175
#[cfg(feature = "salsa_unstable")]
174-
fn memory_usage(&self, _db: &dyn Database) -> Option<Vec<crate::database::SlotInfo>> {
175-
None
176+
fn memory_usage(&self, db: &dyn Database, visitor: &mut dyn MemoryUsageVisitor) {
177+
let _ = (db, visitor);
176178
}
177179
}
178180

src/input.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use crate::sync::Arc;
1919
use crate::table::memo::{MemoTable, MemoTableTypes};
2020
use crate::table::{Slot, Table};
2121
use crate::zalsa::{IngredientIndex, Zalsa};
22+
#[cfg(feature = "salsa_unstable")]
23+
use crate::MemoryUsageVisitor;
2224
use crate::{Database, Durability, Id, Revision, Runtime};
2325

2426
pub trait Configuration: Any {
@@ -42,7 +44,10 @@ pub trait Configuration: Any {
4244
type Durabilities: Send + Sync + fmt::Debug + IndexMut<usize, Output = Durability>;
4345

4446
/// Returns the size of any heap allocations in the output value, in bytes.
45-
fn heap_size(_value: &Self::Fields) -> Option<usize> {
47+
fn heap_size(
48+
_value: &Self::Fields,
49+
_visitor: &mut dyn crate::MemoryUsageVisitor,
50+
) -> Option<usize> {
4651
None
4752
}
4853
}
@@ -252,14 +257,12 @@ impl<C: Configuration> Ingredient for IngredientImpl<C> {
252257

253258
/// Returns memory usage information about any inputs.
254259
#[cfg(feature = "salsa_unstable")]
255-
fn memory_usage(&self, db: &dyn Database) -> Option<Vec<crate::database::SlotInfo>> {
256-
let memory_usage = self
257-
.entries(db)
260+
fn memory_usage(&self, db: &dyn Database, visitor: &mut dyn MemoryUsageVisitor) {
261+
for value in self.entries(db) {
258262
// SAFETY: The memo table belongs to a value that we allocated, so it
259263
// has the correct type.
260-
.map(|value| unsafe { value.memory_usage(&self.memo_table_types) })
261-
.collect();
262-
Some(memory_usage)
264+
unsafe { value.memory_usage(&self.memo_table_types, visitor) }
265+
}
263266
}
264267
}
265268

@@ -311,18 +314,23 @@ where
311314
///
312315
/// The `MemoTable` must belong to a `Value` of the correct type.
313316
#[cfg(feature = "salsa_unstable")]
314-
unsafe fn memory_usage(&self, memo_table_types: &MemoTableTypes) -> crate::database::SlotInfo {
315-
let heap_size = C::heap_size(&self.fields);
317+
unsafe fn memory_usage(
318+
&self,
319+
memo_table_types: &MemoTableTypes,
320+
visitor: &mut dyn MemoryUsageVisitor,
321+
) {
322+
let heap_size = C::heap_size(&self.fields, visitor);
316323
// SAFETY: The caller guarantees this is the correct types table.
317324
let memos = unsafe { memo_table_types.attach_memos(&self.memos) };
318325

319-
crate::database::SlotInfo {
326+
visitor.visit_input_struct(crate::database::StructMemoryInfo {
320327
debug_name: C::DEBUG_NAME,
321328
size_of_metadata: std::mem::size_of::<Self>() - std::mem::size_of::<C::Fields>(),
322329
size_of_fields: std::mem::size_of::<C::Fields>(),
323330
heap_size_of_fields: heap_size,
324-
memos: memos.memory_usage(),
325-
}
331+
});
332+
333+
memos.memory_usage(visitor);
326334
}
327335
}
328336

0 commit comments

Comments
 (0)