-
Notifications
You must be signed in to change notification settings - Fork 214
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
move durable-Kind nextInstanceID out to separate vatstore key #7364
Labels
enhancement
New feature or request
liveslots
requires vat-upgrade to deploy changes
SwingSet
package: SwingSet
Comments
warner
added
enhancement
New feature or request
SwingSet
package: SwingSet
liveslots
requires vat-upgrade to deploy changes
labels
Apr 9, 2023
warner
added a commit
that referenced
this issue
Apr 12, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 12, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 12, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 12, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 13, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 13, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 15, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
warner
added a commit
that referenced
this issue
Apr 15, 2023
Previously, we stored both the static parts of a DurableKindDescriptor (tag, stateShape) and the dynamic part (nextInstanceID) in the same vatStore key (`vom.dkind.${kindID}`). This meant we had to re-write the whole thing each time we make a new instance, which seems like a waste. This change splits the next instance ID out to a separate key: * `vom.dkind.${kindID}.descriptor`: holds the static descriptor * `vom.dkind.${kindID}.nextID`: holds the next instance ID Note that KindIDs are always integers, and we always append the .descriptor/.nextID suffix, so I'm not worried about vatstore key confusion/collision. It also changes the merely-virtual Kind descriptor key to match: `vom.vkind.${kindID}.descriptor`. Note that we don't bother recording a `nextID` for virtual Kinds, since these never outlive an incarnation, so we can hold the nextInstanceID in RAM. We only write out the descriptor for external tooling and debugging, anyways. Internally, `nextInstanceID` is now a BigInt, because we use `Nat()` on the value we get back from the vatstore. This is not exposed to userspace, and vrefs are strings (which incorporate the ID). closes #7364
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
enhancement
New feature or request
liveslots
requires vat-upgrade to deploy changes
SwingSet
package: SwingSet
What is the Problem Being Solved?
Currently, for each virtual Kind, we store a single vatstore key named
vom.vkind.${kindID}
, with a metadata record named the "Kind Descriptor". This contains{ kindID, tag }
, and eitherunfaceted: true
orfacets: [facetName1, facetName2, ..]
.Durable Kinds get the same thing, except in a key named
vom.dkind.${kindID}
, and they get an additional property namednextInstanceID
(an integer, incremented each time an instance of this kind is created).Once #7338 is implemented, the descriptors will also include a serialized
stateShape
capdata record (with{ body, slots }
). For durable Kinds, this may be allowed to change during subsequentbuildRootObject
calls (subject to some innovation on shape-compatibility -checking functions).For virtual kinds, the descriptor is written to the vatstore during
buildRootObject
(or some later crank, whichever one callsdefineDurableKind
), and never read again, because it is also remembered in RAM for the remainder of the incarnation. It ought to be deleted during upgrade, since no virtual (non-durable) objects survive an upgrade, but don't currently delete thevkind
records. We write this descriptor for completeness, and to support debugging/recovery of merely-virtual data. It is not needed for operational purposes.For durable kinds, we write the initial descriptor during the crank that creates the Kind, and again each time
nextInstanceID
is incremented. ThenextInstanceID
counter is also kept in RAM (and hence we don't do a vatstore read on each new allocation), but we write the record out after each allocation so the DB form is accurate: a subsequent incarnation needs to allocate new instances from the right starting point, and not assign duplicate IDs to distinct objects. After each upgrade, we'll read the descriptor duringbuildRootObject
to compare the facet/unfaceted "facetiousness" against the earlier version, to ensure that it hasn't changed (userspace is required to redefine all durable Kinds, but is not allowed to change the facetiousness or change the names or number of the facets).As raised in #7338 (comment) :
Description of the Design
We'll move the Kind Descriptor to
vom.dkind.${kindID}.descriptor
. However we'll removenextInstanceID
from that descriptor, and record it in a separate key,vom.dkind.${kindID}.nextID
.During the first crank that calls
defineDurableKind
, we'll write out both records:vom.dkind.${kindID}.descriptor
:{ kindID, tag, unfaceted | facets, stateShape }
vom.dkind.${kindID}.nextID
:1
Both values are held in RAM, so we won't read these keys again for the remainder of the incarnation.
Each time a new instance is allocated, in addition to updating the in-RAM counter, we'll write a new copy of the counter out to
vom.dkind.${kindID}.nextID
.At the start of the next incarnation, during
buildRootObject
(whendefineDurableKind
is mandated to be called for all existing durable kinds), we'll read both records, to initialize the RAM values. We may also write out a new Kind Descriptor, if/when we allow the stateShape to change, or if we start to include versioning metadata.Security Considerations
When building our vatstore keys (or
kvStore
keys in general), we usually refrain from putting static fields as a suffix to variable fields, to reduce the danger of format/parsing confusion and colliding keys. To follow this guideline, we'd need to create a new prefix for state data, and use vatstore keys more like:vom.dkind.descriptor.${kindID}
vom.dkind.nextID.${kindID}
However I don't want to do that here, because I want the two records for any given kindID to appear next to each other in a sorted dump of the DB. And, I know that
${kindID}
is always an integer (and the only user influence is the fact that they are incremented sequentially, bymakeKindHandle
).In the longer run, we're hoping to get away from using string encoding to build vatstore keys, and get structured data like this stored in SQL more directly (#6677). So we might wind up with a dedicated SQL table for Kinds, with
(kindID, durable, facets, stateShapeCapData, nextID)
as columns, and let SQLite be responsible for efficient caching and hot/cold-ness of different fields.Scaling Considerations
This will slightly increase the space needed per Kind, but remember that Kinds are low-cardinality.
This should slightly improve the speed of creating new Kind instances, because we're writing less data to the vatstore each time (just the new
nextID
counter, rather than re-writing the entire descriptor record).Test Plan
Update unit tests to check that the new keys are in place.
The text was updated successfully, but these errors were encountered: