Skip to content

Commit dd0ae68

Browse files
authored
perf: separate cached and cold fetch paths (#1184)
1 parent 4c843f3 commit dd0ae68

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

benches/compare.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ fn inputs(c: &mut Criterion) {
165165
)
166166
});
167167

168+
group.bench_function(BenchmarkId::new("cached", "Input"), |b| {
169+
let db = salsa::DatabaseImpl::default();
170+
let input = Input::new(&db, "hello, world!".to_owned());
171+
172+
// Prewarm the memo. Every measured call reads a value that has already been verified in
173+
// the current revision.
174+
assert_eq!(length(&db, input), 13);
175+
176+
b.iter(|| length(black_box(&db), black_box(input)))
177+
});
178+
168179
group.bench_function(BenchmarkId::new("new", "SupertypeInput"), |b| {
169180
b.iter_batched_ref(
170181
|| {

src/function/fetch.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ where
5959
let memo_ingredient_index = self.memo_ingredient_index(zalsa, id);
6060

6161
loop {
62-
if let Some(memo) = self
63-
.fetch_hot(zalsa, id, memo_ingredient_index)
64-
.or_else(|| self.fetch_cold(zalsa, zalsa_local, db, id, memo_ingredient_index))
65-
{
62+
// Keep the hot and cold probes in distinct control-flow blocks. Using `or_else`
63+
// here can outline both into one function, making hot hits pay for the cold path's
64+
// stack frame.
65+
if let Some(memo) = self.fetch_hot(zalsa, id, memo_ingredient_index) {
66+
return memo;
67+
}
68+
69+
if let Some(memo) = self.fetch_cold(zalsa, zalsa_local, db, id, memo_ingredient_index) {
6670
return memo;
6771
}
6872
}

0 commit comments

Comments
 (0)