-
Notifications
You must be signed in to change notification settings - Fork 185
Initial persistent caching prototype #967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial persistent caching prototype #967
Conversation
✅ Deploy Preview for salsa-rs canceled.
|
8931c07
to
caf7925
Compare
deserialize_fn: Some(deserialize_fn), | ||
}) => Some(quote! { (#serialize_fn, #deserialize_fn) }), | ||
// Fallback to the `{Serialize, Deserialize}` implementations tuples if only one of the | ||
// two is provided. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a little bit of weirdness here in that all of the following are accepted:
#[salsa::tracked(serialize)]
#[salsa::tracked(deserialize)]
#[salsa::tracked(serialize, deserialize)]
#[salsa::tracked(serialize = ...)]
#[salsa::tracked(deserialize = ...)]
#[salsa::tracked(serialize = ..., deserialize = ...)]
struct ...;
But I'm not sure disallowing any of those is better. With the derive-macro API, we should be able to get rid of this anyways and just use serde::{Serialize, Deserialize}
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this into a persist
attribute to make things more consistent:
#[salsa::tracked(persist)]
#[salsa::tracked(persist(serialize = ...))]
#[salsa::tracked(persist(deserialize = ...))]
#[salsa::tracked(persist(serialize = ..., deserialize = ...))]
struct ...;
We don't accept the serialize
and deserialize
arguments on tracked functions because both the input and output types need to implement serde::{Serialize, Deserialize}
, and the arguments would be ambiguous.
CodSpeed Performance ReportMerging #967 will improve performances by 8.88%Comparing Summary
Benchmarks breakdown
|
77b1f21
to
15a3110
Compare
src/database.rs
Outdated
let DeserializeIngredients(zalsa) = self; | ||
|
||
while let Some(name) = access.next_key::<&str>()? { | ||
// TODO: Serialize the ingredient index directly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically the debug name is not a unique identifier, but I found it more helpful for debugging than the ingredient index. It could also just be a field on each ingredient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A separate (maybe even optinal) field would make sense to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the debug name for now, it's unfortunately very annoying to add extra fields because serde's macros aren't compatible with DeserializeSeed
(which we need for some fields, because we deserialize into the table directly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. I didn't read line by line and instead focused on the overall design.
What's your plan with this PR? Do you want to land it behind a persistence
feature or do you want to keep iterating in a separate branch?
src/database.rs
Outdated
// Ensure structs are serialized before tracked functions, as deserializing a | ||
// memo requires its input struct to have been deserialized. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine deferring this to later but that will mean that we always serialize all tracked structs even if some query instances are never serialized (that created those tracked structs)
src/database.rs
Outdated
let DeserializeIngredients(zalsa) = self; | ||
|
||
while let Some(name) = access.next_key::<&str>()? { | ||
// TODO: Serialize the ingredient index directly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A separate (maybe even optinal) field would make sense to me.
tests/serialize.rs
Outdated
<dyn salsa::Database>::deserialize( | ||
&mut db, | ||
&mut serde_json::Deserializer::from_str(&serialized), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does deserialize
bump the revision to 2
to force a validation of all queries?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm no, should it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are a few things to consider here
- memos and other ingredients that weren't verified in the last revision (current when deserializing) still need to be dirty. The easiest here might be to only serialize ingredients that are verified in the current revision and we revisit this later
- we need to bump the revision if any input changes during deserialization. Now, we don't support this yet so it's fine to ignore for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memos and other ingredients that weren't verified in the last revision (current when deserializing) still need to be dirty. The easiest here might be to only serialize ingredients that are verified in the current revision and we revisit this later
We serialize and deserialize the current revision of the database, so I don't think this is a problem. Any ingredients that weren't verified in the last revision will have to be verified after deserialization.
d30ee9d
to
5e1a984
Compare
7c469e0
to
03377ef
Compare
I gated everything under a |
206d738
to
76a794b
Compare
76a794b
to
b7e5658
Compare
fecc37d
to
4103798
Compare
The overall design is laid out in this document. All the new functionality is gated under the
persistence
feature. However, this PR has a couple of limitations: