# 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.