Skip to content

Use inventory for static ingredient registration#934

Merged
MichaReiser merged 7 commits into
salsa-rs:masterfrom
ibraheemdev:ibraheem/inventory
Jul 18, 2025
Merged

Use inventory for static ingredient registration#934
MichaReiser merged 7 commits into
salsa-rs:masterfrom
ibraheemdev:ibraheem/inventory

Conversation

@ibraheemdev

Copy link
Copy Markdown
Member

Salsa currently registers ingredients dynamically the first time they are accessed, but persistent caching will require that all serializable ingredients are registered up-front. It's possible that we may switch to a static ingredient registration API, but as a first step, we can use inventory to ensure all ingredients have stable indices. This should enable persistent caching and also give us the same performance benefits of static ingredient registration without a large breaking API change.

Inventory has pretty good platform support, I believe it includes all the platforms we care about. There is a caveat on WebAssembly, but I don't think it's a dealbreaker.

@netlify

netlify Bot commented Jul 9, 2025

Copy link
Copy Markdown

Deploy Preview for salsa-rs canceled.

Name Link
🔨 Latest commit 21838e4
🔍 Latest deploy log https://app.netlify.com/projects/salsa-rs/deploys/6879c9d4c190190008dd0059


input.items.push(parse_quote! {
#[cold]
#[inline(never)]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously marked as inline(always), but it's only called in the slow path for both single and multi-database use cases.

@codspeed-hq

codspeed-hq Bot commented Jul 9, 2025

Copy link
Copy Markdown

CodSpeed Performance Report

Merging #934 will improve performances by 29.04%

Comparing ibraheemdev:ibraheem/inventory (21838e4) with master (d28d66b)

Summary

⚡ 9 improvements
✅ 3 untouched benchmarks

Benchmarks breakdown

Benchmark BASE HEAD Change
accumulator 3.8 ms 3.4 ms +12.68%
amortized[Input] 3.5 µs 2.7 µs +29.04%
amortized[InternedInput] 3.4 µs 2.7 µs +25.6%
amortized[SupertypeInput] 4.1 µs 3.3 µs +22.59%
new[Input] 10.5 µs 9.3 µs +13.56%
new[InternedInput] 5.8 µs 4.7 µs +23.58%
new[SupertypeInput] 17.6 µs 15.4 µs +14.2%
converge_diverge 141.6 µs 131.7 µs +7.49%
many_tracked_structs 37.2 µs 32.4 µs +14.65%

Comment thread src/zalsa.rs Outdated
IngredientCache::<I>::UNINITIALIZED,
packed,
Ordering::Release,
Ordering::Relaxed,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I relaxed the failure ordering here because we don't synchronize on failure. FWIW this compare_exchange could even just be a store because it encapsulates all the cached data, but it doesn't really matter.

@ibraheemdev ibraheemdev force-pushed the ibraheem/inventory branch from 502e237 to fab2734 Compare July 9, 2025 20:21
@ibraheemdev

ibraheemdev commented Jul 9, 2025

Copy link
Copy Markdown
Member Author

I believe the benchmark results are somewhat misleading here because they use multiple databases. The fast path for accessing an ingredient is affected less (it doesn't include the HashMap lookup, only the Vec). That said this should be a clear win.

@ibraheemdev

Copy link
Copy Markdown
Member Author

Hmm looks like Miri doesn't support this yet rust-lang/miri#450. That might be the dealbreaker I was anticipating.

@Darksonn

Copy link
Copy Markdown

There are also many projects out there that ban life-before-main including inventory for various reasons including linker issues. For example, if salsa used inventory, we would never be able to import it into the Android codebase.

) -> &$zalsa::interned::IngredientImpl<$Configuration> {
let zalsa = db.zalsa();
$INTERN_CACHE.get_or_create(zalsa, || {
<dyn $Db as $Db>::zalsa_register_downcaster(db);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not exactly sure why this was here before, I don't think it's necessary. It's clearer now because we register the downcaster on the function ingredient directly.

@ibraheemdev

ibraheemdev commented Jul 10, 2025

Copy link
Copy Markdown
Member Author

There are also many projects out there that ban life-before-main including inventory for various reasons including linker issues. For example, if salsa used inventory, we would never be able to import it into the Android codebase.

I think the ideal approach would be to make this an optional feature, and users who can't use inventory can register ingredients manually instead.

Out of curiosity, does the Android codebase support linkme?

@ibraheemdev

Copy link
Copy Markdown
Member Author

I added a simple API for manual ingredient registration. This is just blocked on rust-lang/miri#4459 for Miri support (to avoid rewriting all of our tests to use manual registration).

Comment thread src/database_impl.rs Outdated
Comment thread src/zalsa.rs Outdated
Comment thread components/salsa-macro-rules/src/setup_tracked_fn.rs Outdated
Comment thread src/ingredient_cache.rs Outdated
Comment thread tests/manual_registration.rs Outdated
Comment thread src/zalsa.rs
Comment thread src/ingredient_cache.rs Outdated
Comment on lines +81 to +84
// It doesn't matter if we overwrite any stores, as `create_index` should
// always return the same index.
self.ingredient_index
.store(ingredient_index.as_u32(), Ordering::Release);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is guaranteed when using manual registration because different databases can have different registered ingredients.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm you're right. I guess we still need the nonce check when the inventory feature is disabled? You shouldn't be able to register any ingredients manually that weren't already registered when inventory is enabled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this does mean that our inventory feature isn't strictly addeditve because you won't be able to use the manual registration functions when using inventory (or you can, they're just ignored)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the inventory feature you can't create an ingredient except that it's automatically registered.

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. This is awesome.

I wonder if this also fixes the non-determinism when replaying multithreaded tests.

Requesting review from David/Lukas to get a thumbs up/down from the r-a side

Do you know how far off the miri changes are? Also, have you tested if the ty playground wroks with this new salsa version?

Comment thread src/ingredient_cache.rs Outdated

@davidbarsky davidbarsky left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that miri supports this + this is a substantial speedup, i think we're okay with landing this. if we run into issues, well, we know where to report.

@MichaReiser MichaReiser added this pull request to the merge queue Jul 18, 2025
Merged via the queue into salsa-rs:master with commit dba66f1 Jul 18, 2025
12 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 18, 2025
ibraheemdev added a commit to astral-sh/ruff that referenced this pull request Jul 18, 2025
@github-actions github-actions Bot mentioned this pull request Oct 9, 2025
KotlinIsland pushed a commit to KotlinIsland/basedpython that referenced this pull request May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants