mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 21:05:11 +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
|
## 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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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/).
|
||||||
|
|
Loading…
Reference in a new issue