Merge FallbackImmediate and Fixpoint code paths#1063
Merge FallbackImmediate and Fixpoint code paths#1063MichaReiser merged 4 commits intosalsa-rs:masterfrom
FallbackImmediate and Fixpoint code paths#1063Conversation
✅ Deploy Preview for salsa-rs canceled.
|
FallbackImmediate and Fixpoint code paths
| // For Fixpoint, ask the recovery function what value to use and check convergence. | ||
| let value_converged = if C::CYCLE_STRATEGY == CycleRecoveryStrategy::FallbackImmediate { | ||
| // Use the fallback value instead of the computed value. | ||
| new_value = C::cycle_initial(db, id, C::id_to_input(zalsa, id)); |
There was a problem hiding this comment.
I opted for calling C::cycle_initial here again because it is easier than Cloning (would require a new method on C that panics for all other recovery strategies or we make CycleRecoverStrategy a trait). But I (or someone else ;)) can look into cloning if that's desired or, what would even be better, adding an API that allows us to "take" a value from a Memo (which would also allow us to pass an owned value to recover_from_cycle)
There was a problem hiding this comment.
Having a way to take the value would also be nice in fetch_cold_cycle where we need to call remove_all_except (requiring Atomics) to remove the cycle heads from the previous iteration because we can't create a new memo with the same value but slightly different metadata.
I tried to implement this once but it touches on Salsa parts that I'm not at all familiar with, which is why I ended up going for atomics
| // check if there's a provisional value for this query | ||
| // Note we don't `validate_may_be_provisional` the memo here as we want to reuse an | ||
| // existing provisional memo if it exists | ||
| let memo_guard = self.get_memo_from_table_for(zalsa, id, memo_ingredient_index); |
There was a problem hiding this comment.
I moved this into the cycle handling branch to help the compiler eliminate it for queries without cycle handling
|
CC: @ChayimFriedman2 |
| } | ||
|
|
||
| #[salsa::tracked] | ||
| #[salsa::tracked(cycle_result=two_queries_cycle_result)] |
There was a problem hiding this comment.
The test works regardless of whether we add cycle handling here but adding cycle handling is "more correct" because two_queries2 requires cycle handling if it is called before two_queries1
a0ea2ed to
5b3b99b
Compare
5b3b99b to
5c376e2
Compare
Merging this PR will degrade performance by 6.91%
Performance Changes
Comparing |
carljm
left a comment
There was a problem hiding this comment.
Looks good to me, thank you.
5c376e2 to
e82b78e
Compare
|
We have reports (rust-lang/rust-analyzer#21610 (comment)) that this PR made rust-analyzer constantly use high CPU and emit Salsa warnings. |
|
Micha is out until March, and I unfortunately am not very familiar with usage of |
Summary
Spinned out of #1059 (comment)
This PR removes most special casing of
FallbackImmediateand, instead, integrates it into the normalFixpointcode. Not only should this fix the caching issues thatFallbackImmediatehas today, it also reduces overall complexity and makes it easier to make changes to how we handle cycles in Salsa (no need to update two completely different implementations).This PR preserves the existing
FallbackImmediatebehavior where all heads participating in a query use their fallback value (and not just the cycle heads). I now believe that this behavior is essential for deterministic outputs, as pointed out by Carl in #798 (comment)See
salsa/src/function/execute.rs
Lines 96 to 107 in b6398ec
This PR is based on top of #1062
One difference worth mentioning is that we now overapproximate the dependencies for queries with
cycle_result, keeping all dependencies rather than just those up to the initial cycle. This is fine as it is, and I'm not aware of an easy way to remember when we hit the cycle and which dependencies we've seen up to this point.