Skip to content

Commit

Permalink
feat(swingset): send to promise avoid trip through run-queue
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Apr 29, 2022
1 parent f57b340 commit 9f38bce
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 52 deletions.
52 changes: 42 additions & 10 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ export default function buildKernel(
* This does not decrement any refcounts. The caller should do that.
*
* @param { RunQueueEventSend } message
* @returns { { vatID: VatID, targetObject: string } | null }
* @returns { { vatID: VatID | null, targetObject: string } | null }
*/
function routeSendEvent(message) {
const { target, msg } = message;
Expand All @@ -762,9 +762,9 @@ export default function buildKernel(
return { vatID, targetObject };
}

function enqueue() {
kernelKeeper.addMessageToPromiseQueue(target, msg);
return null; // message is queued, not sent to a vat right now
function requeue() {
// message will be requeued, not sent to a vat right now
return { vatID: null, targetObject: target };
}

if (type === 'object') {
Expand All @@ -788,7 +788,7 @@ export default function buildKernel(
}
case 'unresolved': {
if (!kp.decider) {
return enqueue();
return requeue();
} else {
insistVatID(kp.decider);
// eslint-disable-next-line no-use-before-define
Expand All @@ -800,7 +800,7 @@ export default function buildKernel(
if (deciderVat.enablePipelining) {
return { vatID: kp.decider, targetObject: target };
}
return enqueue();
return requeue();
}
}
default:
Expand Down Expand Up @@ -881,10 +881,20 @@ export default function buildKernel(
if (message.type === 'send') {
useMeter = true;
const route = routeSendEvent(message);
decrementSendEventRefCount(message);
if (route) {
if (!route) {
// Message went splat
decrementSendEventRefCount(message);
} else {
vatID = route.vatID;
deliverP = processSend(vatID, route.targetObject, message.msg);
if (vatID) {
decrementSendEventRefCount(message);
deliverP = processSend(vatID, route.targetObject, message.msg);
} else {
kernelKeeper.addMessageToPromiseQueue(
route.targetObject,
message.msg,
);
}
}
} else if (message.type === 'notify') {
useMeter = true;
Expand Down Expand Up @@ -1089,7 +1099,29 @@ export default function buildKernel(
/** @type { PolicyInput } */
const policyInput = ['none'];

kernelKeeper.addToRunQueue(message);
if (message.type === 'send') {
const route = routeSendEvent(message);
if (!route) {
// Message went splat
decrementSendEventRefCount(message);
} else {
const { vatID, targetObject: target } = route;
if (target !== message.target) {
kernelKeeper.decrementRefCount(message.target, `deq|msg|t`);
kernelKeeper.incrementRefCount(target, `enq|msg|t`);
}
if (vatID) {
kernelKeeper.addToRunQueue({
...message,
target,
});
} else {
kernelKeeper.addMessageToPromiseQueue(target, message.msg);
}
}
} else {
kernelKeeper.addToRunQueue(message);
}

kernelKeeper.processRefcounts();
kernelKeeper.saveStats();
Expand Down
21 changes: 0 additions & 21 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -832,27 +832,6 @@ export default function makeKernelKeeper(
insistKernelType('promise', kernelSlot);
insistMessage(msg);

// Each message on a promise's queue maintains a refcount to the promise
// itself. This isn't strictly necessary (the promise will be kept alive
// by the deciding vat's clist, or the queued message that holds this
// promise as its result), but it matches our policy with run-queue
// messages (each holds a refcount on its target), and makes it easier to
// transfer these messages back to the run-queue in
// resolveKernelPromise() (which doesn't touch any of the refcounts).

// eslint-disable-next-line no-use-before-define
incrementRefCount(kernelSlot, `pq|${kernelSlot}|t`);
if (msg.result) {
// eslint-disable-next-line no-use-before-define
incrementRefCount(msg.result, `pq|${kernelSlot}|r`);
}
let idx = 0;
for (const kref of msg.args.slots) {
// eslint-disable-next-line no-use-before-define
incrementRefCount(kref, `pq|${kernelSlot}|s${idx}`);
idx += 1;
}

const p = getKernelPromise(kernelSlot);
assert(
p.state === 'unresolved',
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/test/message-patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ export function buildPatterns(log) {
return pipe2;
};
}
out.a70 = ['pipe1', 'pipe2', 'pipe3', 'p1.then', 'p2.then', 'p3.then'];
out.a70 = ['pipe1', 'p1.then', 'pipe2', 'p2.then', 'pipe3', 'p3.then'];
outPipelined.a70 = [
'pipe1',
'pipe2',
Expand Down
34 changes: 15 additions & 19 deletions packages/SwingSet/test/test-kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1352,17 +1352,11 @@ const pipelinedSendTest = async (t, delayed) => {
},
]);

// move foo send from acceptance to run-queue
// move foo send from acceptance to run-queue/p0-queue
await kernel.step();
// move bar send from acceptance to run-queue
await kernel.step();
// move urgh send from acceptance to run-queue
await kernel.step();
// deliver/move foo send from run-queue to vatB/p0-queue
await kernel.step();
// deliver/move bar send from run-queue to vatB/p1-queue
// move bar send from acceptance to p1-queue
await kernel.step();
// deliver/move urgh send from run-queue to vatB/p2-queue
// move urgh send from acceptance to p2-queue
await kernel.step();

if (delayed) {
Expand Down Expand Up @@ -1428,17 +1422,19 @@ const pipelinedSendTest = async (t, delayed) => {

// move foo send from acceptance to run-queue
await kernel.step();
// deliver foo send from run-queue to vatB
await kernel.step();
// move bar send from acceptance to run-queue
await kernel.step();
// deliver bar send from run-queue to vatB
await kernel.step();
// move urgh send from acceptance to run-queue
await kernel.step();
// deliver urgh send from run-queue to vatB
await kernel.step();
}
// deliver foo send from run-queue to vatB
// move bar send from p1-queue to acceptance queue
await kernel.step();
// move bar send from acceptance to run-queue
await kernel.step();
// deliver bar send from run-queue to vatB
// move urgh send from p2-queue to acceptance queue
await kernel.step();
// move urgh send from acceptance to run-queue
await kernel.step();
// deliver urgh send from run-queue to vatB
await kernel.step();

const p1ForB = kernel.addImport(vatB, p1ForKernel);
const p2ForB = kernel.addImport(vatB, p2ForKernel);
Expand Down
2 changes: 2 additions & 0 deletions packages/SwingSet/test/test-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,13 @@ test('kernelKeeper promises', async t => {
const expectedAcceptanceQueue = [];
const m1 = { method: 'm1', args: { body: '', slots: [] } };
k.addMessageToPromiseQueue(p1, m1);
k.incrementRefCount(p1);
t.deepEqual(k.getKernelPromise(p1).refCount, 1);
expectedAcceptanceQueue.push({ type: 'send', target: 'kp40', msg: m1 });

const m2 = { method: 'm2', args: { body: '', slots: [] } };
k.addMessageToPromiseQueue(p1, m2);
k.incrementRefCount(p1);
t.deepEqual(k.getKernelPromise(p1).queue, [m1, m2]);
t.deepEqual(k.getKernelPromise(p1).refCount, 2);
expectedAcceptanceQueue.push({ type: 'send', target: 'kp40', msg: m2 });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ async function doTerminate(t, mode, reference, extraMessage = []) {
...extraMessage,
'foreverP.catch Error: vat terminated',
'query3P.catch Error: vat terminated',
'foo4P.catch Error: vat terminated',
'afterForeverP.catch Error: vat terminated',
'foo4P.catch Error: vat terminated',
reference,
'done',
]);
Expand Down

0 comments on commit 9f38bce

Please sign in to comment.