mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 12:56:33 +00:00
Start proofreading the 'how salsa works' section
This commit is contained in:
parent
0f7a8c33ae
commit
454e5518d2
3 changed files with 22 additions and 29 deletions
|
@ -2,8 +2,8 @@
|
|||
|
||||
## Video available
|
||||
|
||||
To get the most complete introduction to salsa's inner works, check
|
||||
out [the "How Salsa Works" video](https://youtu.be/_muY4HjSqVw). If
|
||||
To get the most complete introduction to salsa's inner workings, check
|
||||
out [the "How Salsa Works" video](https://youtu.be/_muY4HjSqVw). If
|
||||
you'd like a deeper dive, [the "Salsa in more depth"
|
||||
video](https://www.youtube.com/watch?v=i_IhACacPRY) digs into the
|
||||
details of the incremental algorithm.
|
||||
|
@ -13,14 +13,14 @@ details of the incremental algorithm.
|
|||
## Key idea
|
||||
|
||||
The key idea of `salsa` is that you define your program as a set of
|
||||
**queries**. Every query is used like function `K -> V` that maps from
|
||||
**queries**. Every query is used like a function `K -> V` that maps from
|
||||
some key of type `K` to a value of type `V`. Queries come in two basic
|
||||
varieties:
|
||||
|
||||
- **Inputs**: the base inputs to your system. You can change these
|
||||
whenever you like.
|
||||
- **Functions**: pure functions (no side effects) that transform your
|
||||
inputs into other values. The results of queries is memoized to
|
||||
inputs into other values. The results of queries are memoized to
|
||||
avoid recomputing them a lot. When you make changes to the inputs,
|
||||
we'll figure out (fairly intelligently) when we can re-use these
|
||||
memoized values and when we have to recompute them.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{{#include ../caveat.md}}
|
||||
|
||||
This page covers how data is organized in salsa and how links between salsa items (e.g., dependency tracking) works.
|
||||
This page covers how data is organized in salsa and how links between salsa items (e.g., dependency tracking) work.
|
||||
|
||||
## Salsa items and ingredients
|
||||
|
||||
|
@ -32,7 +32,7 @@ Each salsa item needs certain bits of data at runtime to operate.
|
|||
These bits of data are called **ingredients**.
|
||||
Most salsa items generate a single ingredient, but sometimes they make more than one.
|
||||
For example, a tracked function generates a [`FunctionIngredient`].
|
||||
A tracked struct however generates several ingredients, one for the struct itself (a [`TrackedStructIngredient`],
|
||||
A tracked struct, however, generates several ingredients, one for the struct itself (a [`TrackedStructIngredient`],
|
||||
and one [`FunctionIngredient`] for each value field.
|
||||
|
||||
[`FunctionIngredient`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/function.rs#L42
|
||||
|
@ -50,13 +50,6 @@ or whether the function must be executed.
|
|||
[`TrackedStruct::new_struct`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/tracked_struct.rs#L76
|
||||
[`TrackedFunction::fetch`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/function/fetch.rs#L15
|
||||
|
||||
### Ingredient interfaces are not stable or subject to semver
|
||||
|
||||
Interfaces are not meant to be directly used by salsa users.
|
||||
The salsa macros generate code that invokes the ingredients.
|
||||
The APIs may change in arbitrary ways across salsa versions,
|
||||
as the macros are kept in sync.
|
||||
|
||||
### The `Ingredient` trait
|
||||
|
||||
Each ingredient implements the [`Ingredient<DB>`] trait, which defines generic operations supported by any kind of ingredient.
|
||||
|
@ -65,8 +58,8 @@ For example, the method `maybe_changed_after` can be used to check whether some
|
|||
[`Ingredient<DB>`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/ingredient.rs#L15
|
||||
[`maybe_changed_after`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/ingredient.rs#L21-L22
|
||||
|
||||
We'll see below that each database `DB` is able to take an `IngredientIndex` and use that to get a `&dyn Ingredient<DB>` for the corresponding ingredient.
|
||||
This allows the database to perform generic operations on a numbered ingredient without knowing exactly what the type of that ingredient is.
|
||||
We'll see below that each database `DB` is able to take an `IngredientIndex` and use that to get an `&dyn Ingredient<DB>` for the corresponding ingredient.
|
||||
This allows the database to perform generic operations on an indexed ingredient without knowing exactly what the type of that ingredient is.
|
||||
|
||||
### Jars are a collection of ingredients
|
||||
|
||||
|
@ -91,13 +84,12 @@ struct Jar(
|
|||
)
|
||||
```
|
||||
|
||||
The `IngredientsFor` trait is used to define the ingredients needed by some salsa item, such as the tracked function `foo`
|
||||
or the tracked struct `MyInput`.
|
||||
Each salsa item defines a type `I`, so that `<I as IngredientsFor>::Ingredient` gives the ingredients needed by `I`.
|
||||
The `IngredientsFor` trait is used to define the ingredients needed by some salsa item, such as the tracked function `foo` or the tracked struct `MyInput`.
|
||||
Each salsa item defines a type `I` so that `<I as IngredientsFor>::Ingredient` gives the ingredients needed by `I`.
|
||||
|
||||
### Database is a tuple of jars
|
||||
### A database is a tuple of jars
|
||||
|
||||
Salsa's database storage ultimately boils down to a tuple of jar structs,
|
||||
salsa's database storage ultimately boils down to a tuple of jar structs
|
||||
where each jar struct (as we just saw) itself contains the ingredients
|
||||
for the salsa items within that jar.
|
||||
The database can thus be thought of as a list of ingredients,
|
||||
|
@ -107,7 +99,7 @@ The reason for this 2-level hierarchy is that it permits separate compilation an
|
|||
The crate that lists the jars doens't have to know the contents of the jar to embed the jar struct in the database.
|
||||
And some of the types that appear in the jar may be private to another struct.
|
||||
|
||||
### The HasJars trait and the Jars type
|
||||
### The `HasJars` trait and the `Jars` type
|
||||
|
||||
Each salsa database implements the `HasJars` trait,
|
||||
generated by the `salsa::db` procedural macro.
|
||||
|
@ -167,15 +159,16 @@ We can then do things like ask, "did this input change since revision R?" by
|
|||
* using the ingredient index to find the route and get a `&dyn Ingredient<DB>`
|
||||
* and then invoking the `maybe_changed_since` method on that trait object.
|
||||
|
||||
### HasJarsDyn
|
||||
### `HasJarsDyn`
|
||||
|
||||
There is one catch in the above setup.
|
||||
We need the database to be dyn-safe, and we also need to be able to define the database trait and so forth without knowing the final database type to enable separate compilation.
|
||||
We need the database to be dyn-safe [what does this mean?], and we also need to be able to define the database trait without knowing the final database type to enable separate compilation.
|
||||
Traits like `Ingredient<DB>` require knowing the full `DB` type.
|
||||
If we had one function ingredient directly invoke a method on `Ingredient<DB>`, that would imply that it has to be fully generic and only instantiated at the final crate, when the full database type is available.
|
||||
|
||||
We solve this via the `HasJarsDyn` trait. The `HasJarsDyn` trait exports method that combine the "find ingredient, invoking method" steps into one method:
|
||||
We solve this via the `HasJarsDyn` trait. The `HasJarsDyn` trait exports a method that combines the "find ingredient, invoking method" steps into one method:
|
||||
|
||||
[Perhaps this code snippet should only preview the HasJarsDyn method that is being referred to]
|
||||
```rust,ignore
|
||||
{{#include ../../../components/salsa-2022/src/storage.rs:HasJarsDyn}}
|
||||
```
|
||||
|
@ -205,13 +198,13 @@ The implementation of this method is defined by the `#[salsa::db]` macro; it sim
|
|||
{{#include ../../../components/salsa-2022-macros/src/db.rs:create_jars}}
|
||||
```
|
||||
|
||||
This implementation for `create_jar` is geneated by the `#[salsa::jar]` macro, and simply walks over the representative type for each salsa item and ask *it* to create its ingredients
|
||||
This implementation for `create_jar` is geneated by the `#[salsa::jar]` macro, and simply walks over the representative type for each salsa item and asks *it* to create its ingredients
|
||||
|
||||
```rust,ignore
|
||||
{{#include ../../../components/salsa-2022-macros/src/jar.rs:create_jar}}
|
||||
```
|
||||
|
||||
The code to create the ingredients for any particular item is generated by their associated macros (e.g., `#[salsa::tracked]`, `#[salsa::input]`), but it always follows a particular structure.
|
||||
To create an ingredient, we first invoke `Routes::push` which creates the routes to that ingredient and assigns it an `IngredientIndex`.
|
||||
We can then invoke (e.g.) `FunctionIngredient::new` to create the structure.
|
||||
To create an ingredient, we first invoke `Routes::push`, which creates the routes to that ingredient and assigns it an `IngredientIndex`.
|
||||
We can then invoke (e.g.) [Missing an example here] `FunctionIngredient::new` to create the structure.
|
||||
The *routes* to an ingredient are defined as closures that, given the `DB::Jars`, can find the data for a particular ingredient.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Videos
|
||||
|
||||
There are currently two videos about Salsa available, but they describe an older version of Salsa and so they are rather outdated:
|
||||
There are currently two videos about salsa available, but they describe an older version of salsa and so they are rather outdated:
|
||||
|
||||
- [How Salsa Works](https://youtu.be/_muY4HjSqVw), which gives a
|
||||
high-level introduction to the key concepts involved and shows how
|
||||
to use salsa;
|
||||
- [Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY),
|
||||
which digs into the incremental algorithm and explains -- at a
|
||||
high-level -- how Salsa is implemented.
|
||||
high-level -- how salsa is implemented.
|
||||
|
||||
> If you're in China, watch videos on [How Salsa Works](https://www.bilibili.com/video/BV1Df4y1A7t3/), [Salsa In More Depth](https://www.bilibili.com/video/BV1AM4y1G7E4/).
|
||||
|
|
Loading…
Reference in a new issue