# Documentation for current setup ```mermaid flowchart TD Database Database --> Storage Storage --> Zalsa Zalsa --> Runtime Runtime --> Table Storage --> ZalsaLocal Table --> Page Page --> Slot Slot --> Memo Zalsa --> Ingredient Ingredient --> TrackedFunctionIngredient Ingredient --> TrackedStructIngredient TrackedFunctionIngredient -- stores --> Memo TrackedStructIngredient -- allocates --> Slot ``` ## How tracked struct allocation works Each new tracked struct is assigned a fresh id. The database has a [thread-local cache per ingredient](https://github.com/salsa-rs/salsa/blob/master/src/zalsa_local.rs#L43) of the most recent page that this ingredient allocated on this thread. Allocating a new id comes out of this page first. ### Reuse of ids Today reuse happens when a tracked function produces fewer or different structs than it did in the prior revision. Example: tracked function `f(n: Counter)` that creates structs from `0..n` (`n` is an input). And in R0 `n` is `3` and then we change it to `2` in R1`. Tracked struct #3 is no longer existing in R1. In that case, the `Id` is put into a [free-list](https://github.com/salsa-rs/salsa/blob/884a30cf9d73ce788b50c55c0421055c6ee95936/src/tracked_struct.rs#L141) in the tracked struct ingredient. [Allocation checks this free-list first](https://github.com/salsa-rs/salsa/blob/884a30cf9d73ce788b50c55c0421055c6ee95936/src/tracked_struct.rs#L303-L319). ## How tracked function memos work Architecture as implemented today: Every tracked function takes a single argument of some salsa struct (input/interned/tracked). Every tracked function is assigned a unique `MemoIngredientIndex` `M` (starting from 0, counting up as they are created). Given this argument `A` we can map it to an `Id` and use that to lookup a `Slot`. We then lookup the `slot.memos[m]` to find the memo for this function ingredient. The `memos` array is lazilly allocated to be at least length `m` when a memo is stored. Opportunities for improvement: * Instead of giving each tracked function a unique index, we could give a unique index per the type of tracked struct it takes as argument. * Instead of interning when there is >1 argument, we could convert the memo table to give us not a memo but a map from (extra_arguments -> memo). This would eliminate another global hashmap and improve contention. * When zero arguments, we should probably specialize that to some entirely separate implementation.