You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#455 introduces a mechanism to move large state (lots of small objects, like Purses) from RAM onto disk. It uses new syscalls described in #1831 .
This ticket is about enhancing liveslots to provide this API to userspace code.
Description of the Design
Liveslots will add a new vatPower.createContainer method, which is made available to the vat's root object (who can share it elsewhere as they see fit).
We expect this to be called a small number of times during vat startup, to register a handful of tables. For issuer.js (being converted in #1830), we anticipate two tables: one for Purses, the other for Payments.
Each table gets associated with a constructor function, which will be called to create a Representative on-demand. This function should return a hardened object with callable methods (just like createRootObject). However this object should not hold any internal state (all state should be managed with the c.get/c.update functions it receives). It should (probably?) not close over anything, nor (probably) should it be used in identity comparison functions, pending our conclusions about what identity properties liveslots can afford to guarantee (LRU vs remember-always vs remember-never).
The constructor will be invoked during dispatch.deliver when a matching object ID appears as the target of an inbound message, in which case one of the methods created by the constructor will be invoked immediately. This also happens during dispatch.deliver when the ID appears as an argument, these methods will not necessarily be used, however the representative may appear in the arguments of some other method, which might use c.get() or c.update() to access its state.
The constructor will also be called if/when one Representative uses c.get() to fetch some data, and that data references a second Representative.
This method will use a table that maps from a container ID (a simple counter) with the constructor function and a map from representative ID to Representative object (for whatever subset of the Representatives that we retain, which might be a 100-deep LRU cache, or might be empty, pending our conclusions above). There must also be a map from all Representatives (across all containers) to the (container ID, representative ID) pair.
Liveslots' valToSlot function will be updated to look in this second map as well as the normal Presence/Promise table (or, more likely, the Representatives can just be added to the normal table).
The slotToVal function will be updated to recognize representative IDs, see if an existing Representative object exists, and if not, call the constructor (and maybe adding it to the table).
Representative IDs
We can start with non-hierarchical IDs: Representative IDs will be the same o+NN pattern we've been using all along for Object IDs, and we just increment the integer for each new item added to the Container. This defers the need to support the hierarchical format in the c-lists (and format-checking functions like parseVatSlot).
The liveslots implementation will use the #1831 secondary-storage syscalls to record a mapping from o+NN to (container ID, data).
Later, we can make these hierarchical, to reduce the size of the secondary storage. At that point, the RepresentativeID will be like o+CC.RR. There will be an in-RAM Map from the CC integer to a record that includes the constructor function. The deserialization code will then use the #1831 syscalls to manage mapping from CC.RR to (data), omitting the container ID.
(now that I write that out, I'm not sure what the hierarchy buys us.. I suppose it factors out a couple bytes from each value. If we incorporated hierachical keys directly into the syscalls, and if our backend HostDB could take advantage of that, it might factor out a couple of bytes from the keys as well)
Security Considerations
Test Plan
The text was updated successfully, but these errors were encountered:
What is the Problem Being Solved?
#455 introduces a mechanism to move large state (lots of small objects, like Purses) from RAM onto disk. It uses new syscalls described in #1831 .
This ticket is about enhancing liveslots to provide this API to userspace code.
Description of the Design
Liveslots will add a new
vatPower.createContainer
method, which is made available to the vat's root object (who can share it elsewhere as they see fit).We expect this to be called a small number of times during vat startup, to register a handful of tables. For
issuer.js
(being converted in #1830), we anticipate two tables: one for Purses, the other for Payments.Each table gets associated with a constructor function, which will be called to create a Representative on-demand. This function should return a hardened object with callable methods (just like
createRootObject
). However this object should not hold any internal state (all state should be managed with thec.get
/c.update
functions it receives). It should (probably?) not close over anything, nor (probably) should it be used in identity comparison functions, pending our conclusions about what identity properties liveslots can afford to guarantee (LRU vs remember-always vs remember-never).The constructor will be invoked during
dispatch.deliver
when a matching object ID appears as the target of an inbound message, in which case one of the methods created by the constructor will be invoked immediately. This also happens duringdispatch.deliver
when the ID appears as an argument, these methods will not necessarily be used, however the representative may appear in the arguments of some other method, which might usec.get()
orc.update()
to access its state.The constructor will also be called if/when one Representative uses
c.get()
to fetch some data, and that data references a second Representative.This method will use a table that maps from a container ID (a simple counter) with the constructor function and a map from representative ID to Representative object (for whatever subset of the Representatives that we retain, which might be a 100-deep LRU cache, or might be empty, pending our conclusions above). There must also be a map from all Representatives (across all containers) to the (container ID, representative ID) pair.
Liveslots'
valToSlot
function will be updated to look in this second map as well as the normal Presence/Promise table (or, more likely, the Representatives can just be added to the normal table).The
slotToVal
function will be updated to recognize representative IDs, see if an existing Representative object exists, and if not, call the constructor (and maybe adding it to the table).Representative IDs
We can start with non-hierarchical IDs: Representative IDs will be the same
o+NN
pattern we've been using all along for Object IDs, and we just increment the integer for each new item added to the Container. This defers the need to support the hierarchical format in the c-lists (and format-checking functions likeparseVatSlot
).The liveslots implementation will use the #1831 secondary-storage syscalls to record a mapping from
o+NN
to(container ID, data)
.Later, we can make these hierarchical, to reduce the size of the secondary storage. At that point, the RepresentativeID will be like
o+CC.RR
. There will be an in-RAMMap
from theCC
integer to a record that includes the constructor function. The deserialization code will then use the #1831 syscalls to manage mapping fromCC.RR
to(data)
, omitting the container ID.(now that I write that out, I'm not sure what the hierarchy buys us.. I suppose it factors out a couple bytes from each value. If we incorporated hierachical keys directly into the syscalls, and if our backend HostDB could take advantage of that, it might factor out a couple of bytes from the keys as well)
Security Considerations
Test Plan
The text was updated successfully, but these errors were encountered: