-
Notifications
You must be signed in to change notification settings - Fork 212
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
feat: demand-paged vats in solo, chain #2848
Changes from 27 commits
9582ede
eaf5ae6
e7708a4
7c10cd8
8e6116b
aebbb2f
185704a
5477574
66eaad5
3a8db9f
dc83a0f
f42bdd4
05459c7
73b26a0
aec603d
6fe0712
20e8351
7f365b7
5f8ce81
6b48f1e
abc9c9a
f1a2bc3
3d34bee
f9a1eb2
06158c8
bd9563d
7e05a24
a4b01eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,7 @@ export function initializeVatState(kvStore, streamStore, vatID) { | |
/** | ||
* Produce a vat keeper for a vat. | ||
* | ||
* @param {*} kvStore The keyValue store in which the persistent state will be kept | ||
* @param {KVStorePlus} kvStore The keyValue store in which the persistent state will be kept | ||
* @param {StreamStore} streamStore Accompanying stream store, for the transcripts | ||
* @param {*} kernelSlog | ||
* @param {string} vatID The vat ID string of the vat in question | ||
|
@@ -60,6 +60,7 @@ export function initializeVatState(kvStore, streamStore, vatID) { | |
* @param {*} incStat | ||
* @param {*} decStat | ||
* @param {*} getCrankNumber | ||
* @param { SnapStore= } snapStore | ||
* returns an object to hold and access the kernel's state for the given vat | ||
*/ | ||
export function makeVatKeeper( | ||
|
@@ -79,6 +80,7 @@ export function makeVatKeeper( | |
incStat, | ||
decStat, | ||
getCrankNumber, | ||
snapStore = undefined, | ||
) { | ||
insistVatID(vatID); | ||
const transcriptStream = `transcript-${vatID}`; | ||
|
@@ -417,6 +419,57 @@ export function makeVatKeeper( | |
kvStore.set(`${vatID}.t.endPosition`, `${JSON.stringify(newPos)}`); | ||
} | ||
|
||
/** @returns { StreamPosition } */ | ||
function getTranscriptEndPosition() { | ||
return JSON.parse( | ||
kvStore.get(`${vatID}.t.endPosition`) || | ||
assert.fail('missing endPosition'), | ||
); | ||
} | ||
|
||
/** | ||
* @returns {{ snapshotID: string, startPos: StreamPosition } | undefined} | ||
*/ | ||
function getLastSnapshot() { | ||
const notation = kvStore.get(`${vatID}.lastSnapshot`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please update the big pseudo-schema comment in |
||
if (!notation) { | ||
return undefined; | ||
} | ||
const { snapshotID, startPos } = JSON.parse(notation); | ||
assert.typeof(snapshotID, 'string'); | ||
assert(startPos); | ||
return { snapshotID, startPos }; | ||
} | ||
|
||
function transcriptSnapshotStats() { | ||
const totalEntries = getTranscriptEndPosition().itemCount; | ||
const lastSnapshot = getLastSnapshot(); | ||
const snapshottedEntries = lastSnapshot | ||
? lastSnapshot.startPos.itemCount | ||
: 0; | ||
return { totalEntries, snapshottedEntries }; | ||
} | ||
|
||
/** | ||
* Store a snapshot, if given a snapStore. | ||
* | ||
* @param { VatManager } manager | ||
* @returns { Promise<boolean> } | ||
*/ | ||
async function saveSnapshot(manager) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels awkward, passing a VatManager into the storage layer. I'm inclined to keep VatKeeper only about recording the actions that someone else has taken, rather than taking those actions itself. What about the alternative, where the Vat Warehouse holds the function saveSnapshot() {
if (!snapStore) {
return;
}
const snapshotID = await manager.makeSnapshot(snapStore).
vatKeeper.saveSnapshot(snapshotID);
} and |
||
if (!snapStore || !manager.makeSnapshot) { | ||
return false; | ||
} | ||
|
||
const snapshotID = await manager.makeSnapshot(snapStore); | ||
const endPosition = getTranscriptEndPosition(); | ||
kvStore.set( | ||
`${vatID}.lastSnapshot`, | ||
JSON.stringify({ snapshotID, startPos: endPosition }), | ||
); | ||
return true; | ||
} | ||
|
||
function vatStats() { | ||
function getCount(key, first) { | ||
const id = Nat(BigInt(kvStore.get(key))); | ||
|
@@ -477,8 +530,11 @@ export function makeVatKeeper( | |
deleteCListEntry, | ||
deleteCListEntriesForKernelSlots, | ||
getTranscript, | ||
transcriptSnapshotStats, | ||
addToTranscript, | ||
vatStats, | ||
dumpState, | ||
saveSnapshot, | ||
getLastSnapshot, | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,8 @@ import { makeTranscriptManager } from './transcript.js'; | |
|
||
/** | ||
* | ||
* @typedef { { getManager: (shutdown: () => Promise<void>) => VatManager, | ||
* @typedef { { getManager: (shutdown: () => Promise<void>, | ||
* makeSnapshot?: (ss: SnapStore) => Promise<string>) => VatManager, | ||
* syscallFromWorker: (vso: VatSyscallObject) => VatSyscallResult, | ||
* setDeliverToWorker: (dtw: unknown) => void, | ||
* } } ManagerKit | ||
|
@@ -178,12 +179,18 @@ function makeManagerKit( | |
kernelSlog.write({ type: 'finish-replay-delivery', vatID, deliveryNum }); | ||
} | ||
|
||
async function replayTranscript() { | ||
/** | ||
* @param {StreamPosition | undefined} startPos | ||
* @returns { Promise<number?> } number of deliveries, or null if !useTranscript | ||
*/ | ||
async function replayTranscript(startPos) { | ||
// console.log('replay from', { vatID, startPos }); | ||
|
||
if (transcriptManager) { | ||
const total = vatKeeper.vatStats().transcriptCount; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe not for now, but we should clean up this |
||
kernelSlog.write({ type: 'start-replay', vatID, deliveries: total }); | ||
let deliveryNum = 0; | ||
for (const t of vatKeeper.getTranscript()) { | ||
for (const t of vatKeeper.getTranscript(startPos)) { | ||
// if (deliveryNum % 100 === 0) { | ||
// console.debug(`replay vatID:${vatID} deliveryNum:${deliveryNum} / ${total}`); | ||
// } | ||
|
@@ -194,7 +201,10 @@ function makeManagerKit( | |
} | ||
transcriptManager.checkReplayError(); | ||
kernelSlog.write({ type: 'finish-replay', vatID }); | ||
return deliveryNum; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
|
@@ -235,10 +245,17 @@ function makeManagerKit( | |
/** | ||
* | ||
* @param { () => Promise<void>} shutdown | ||
* @param { (ss: SnapStore) => Promise<string> } makeSnapshot | ||
* @returns { VatManager } | ||
*/ | ||
function getManager(shutdown) { | ||
return harden({ replayTranscript, replayOneDelivery, deliver, shutdown }); | ||
function getManager(shutdown, makeSnapshot) { | ||
return harden({ | ||
replayTranscript, | ||
replayOneDelivery, | ||
deliver, | ||
shutdown, | ||
makeSnapshot, | ||
}); | ||
} | ||
|
||
return harden({ getManager, syscallFromWorker, setDeliverToWorker }); | ||
|
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.
re
snapstore
vssnapStore
, I think this instance is an argument to use the camel-casesnapStore
throughout