Start proofreading the 'how salsa works' section

This commit is contained in:
Sean Chen 2022-08-22 14:16:38 -05:00
parent 0f7a8c33ae
commit 454e5518d2
3 changed files with 22 additions and 29 deletions

View file

@ -2,8 +2,8 @@
## Video available ## Video available
To get the most complete introduction to salsa's inner works, check To get the most complete introduction to salsa's inner workings, check
out [the "How Salsa Works" video](https://youtu.be/_muY4HjSqVw). If out [the "How Salsa Works" video](https://youtu.be/_muY4HjSqVw). If
you'd like a deeper dive, [the "Salsa in more depth" you'd like a deeper dive, [the "Salsa in more depth"
video](https://www.youtube.com/watch?v=i_IhACacPRY) digs into the video](https://www.youtube.com/watch?v=i_IhACacPRY) digs into the
details of the incremental algorithm. details of the incremental algorithm.
@ -13,14 +13,14 @@ details of the incremental algorithm.
## Key idea ## Key idea
The key idea of `salsa` is that you define your program as a set of 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 some key of type `K` to a value of type `V`. Queries come in two basic
varieties: varieties:
- **Inputs**: the base inputs to your system. You can change these - **Inputs**: the base inputs to your system. You can change these
whenever you like. whenever you like.
- **Functions**: pure functions (no side effects) that transform your - **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, avoid recomputing them a lot. When you make changes to the inputs,
we'll figure out (fairly intelligently) when we can re-use these we'll figure out (fairly intelligently) when we can re-use these
memoized values and when we have to recompute them. memoized values and when we have to recompute them.

View file

@ -2,7 +2,7 @@
{{#include ../caveat.md}} {{#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 ## 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**. These bits of data are called **ingredients**.
Most salsa items generate a single ingredient, but sometimes they make more than one. Most salsa items generate a single ingredient, but sometimes they make more than one.
For example, a tracked function generates a [`FunctionIngredient`]. 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. and one [`FunctionIngredient`] for each value field.
[`FunctionIngredient`]: https://github.com/salsa-rs/salsa/blob/becaade31e6ebc58cd0505fc1ee4b8df1f39f7de/components/salsa-2022/src/function.rs#L42 [`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 [`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 [`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 ### The `Ingredient` trait
Each ingredient implements the [`Ingredient<DB>`] trait, which defines generic operations supported by any kind of ingredient. 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 [`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 [`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. 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 a numbered ingredient without knowing exactly what the type of that ingredient is. 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 ### 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` 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`.
or the tracked struct `MyInput`. Each salsa item defines a type `I` so that `<I as IngredientsFor>::Ingredient` gives the ingredients needed by `I`.
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 where each jar struct (as we just saw) itself contains the ingredients
for the salsa items within that jar. for the salsa items within that jar.
The database can thus be thought of as a list of ingredients, 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. 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. 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, Each salsa database implements the `HasJars` trait,
generated by the `salsa::db` procedural macro. 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>` * 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. * and then invoking the `maybe_changed_since` method on that trait object.
### HasJarsDyn ### `HasJarsDyn`
There is one catch in the above setup. 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. 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. 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 ```rust,ignore
{{#include ../../../components/salsa-2022/src/storage.rs:HasJarsDyn}} {{#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}} {{#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 ```rust,ignore
{{#include ../../../components/salsa-2022-macros/src/jar.rs:create_jar}} {{#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. 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`. 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. 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. The *routes* to an ingredient are defined as closures that, given the `DB::Jars`, can find the data for a particular ingredient.

View file

@ -1,12 +1,12 @@
# Videos # 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 - [How Salsa Works](https://youtu.be/_muY4HjSqVw), which gives a
high-level introduction to the key concepts involved and shows how high-level introduction to the key concepts involved and shows how
to use salsa; to use salsa;
- [Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY), - [Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY),
which digs into the incremental algorithm and explains -- at a 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/). > 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/).