Skip to content

Commit

Permalink
fix(xs-worker): respect !managerOptions.metered (#3078)
Browse files Browse the repository at this point in the history
* fix(xs-worker): respect metered from managerOptions

* test(xsnap): meter details are still available with no limit

* feat(swingset): allow caller to supply spawn power

... and use it to test that unmetered XS vats are spawned without the
`-l` metering option.
  • Loading branch information
dckc authored May 17, 2021
1 parent 97f39fa commit 84fa8c9
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 9 deletions.
20 changes: 14 additions & 6 deletions packages/SwingSet/src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import path from 'path';
import process from 'process';
import re2 from 're2';
import { performance } from 'perf_hooks';
import { spawn } from 'child_process';
import { spawn as ambientSpawn } from 'child_process';
import { type as osType } from 'os';
import { Worker } from 'worker_threads';
import anylogger from 'anylogger';
Expand Down Expand Up @@ -46,9 +46,13 @@ function unhandledRejectionHandler(e) {

/**
* @param {{ moduleFormat: string, source: string }[]} bundles
* @param {{ snapstorePath?: string, env: Record<string, string | undefined> }} opts
* @param {{
* snapstorePath?: string,
* spawn: typeof import('child_process').spawn
* env: Record<string, string | undefined>,
* }} opts
*/
export function makeStartXSnap(bundles, { snapstorePath, env }) {
export function makeStartXSnap(bundles, { snapstorePath, env, spawn }) {
/** @type { import('@agoric/xsnap/src/xsnap').XSnapOptions } */
const xsnapOpts = {
os: osType(),
Expand Down Expand Up @@ -79,16 +83,18 @@ export function makeStartXSnap(bundles, { snapstorePath, env }) {
/**
* @param {string} name
* @param {(request: Uint8Array) => Promise<Uint8Array>} handleCommand
* @param { boolean } [metered]
*/
async function startXSnap(name, handleCommand) {
async function startXSnap(name, handleCommand, metered) {
if (supervisorHash) {
return snapStore.load(supervisorHash, async snapshot => {
const xs = xsnap({ snapshot, name, handleCommand, ...xsnapOpts });
await xs.evaluate('null'); // ensure that spawn is done
return xs;
});
}
const worker = xsnap({ handleCommand, name, ...xsnapOpts });
const meterOpts = metered ? {} : { meteringLimit: 0 };
const worker = xsnap({ handleCommand, name, ...meterOpts, ...xsnapOpts });

for (const bundle of bundles) {
assert(
Expand Down Expand Up @@ -117,6 +123,7 @@ export function makeStartXSnap(bundles, { snapstorePath, env }) {
* slogFile?: string,
* testTrackDecref?: unknown,
* snapstorePath?: string,
* spawn?: typeof import('child_process').spawn,
* env?: Record<string, string | undefined>
* }} runtimeOptions
*/
Expand All @@ -137,6 +144,7 @@ export async function makeSwingsetController(
slogCallbacks,
slogFile,
snapstorePath,
spawn = ambientSpawn,
} = runtimeOptions;
if (typeof Compartment === 'undefined') {
throw Error('SES must be installed before calling makeSwingsetController');
Expand Down Expand Up @@ -271,7 +279,7 @@ export async function makeSwingsetController(
// @ts-ignore assume supervisorBundle is set
JSON.parse(hostStorage.get('supervisorBundle')),
];
const startXSnap = makeStartXSnap(bundles, { snapstorePath, env });
const startXSnap = makeStartXSnap(bundles, { snapstorePath, env, spawn });

const kernelEndowments = {
waitUntilQuiescent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const decoder = new TextDecoder();
* allVatPowers: VatPowers,
* kernelKeeper: KernelKeeper,
* kernelSlog: KernelSlog,
* startXSnap: (name: string, handleCommand: SyncHandler) => Promise<XSnap>,
* startXSnap: (name: string, handleCommand: SyncHandler, metered?: boolean) => Promise<XSnap>,
* testLog: (...args: unknown[]) => void,
* }} tools
* @returns { VatManagerFactory }
Expand Down Expand Up @@ -53,6 +53,7 @@ export function makeXsSubprocessFactory({
virtualObjectCacheSize,
enableDisavow,
name,
metered,
} = managerOptions;
assert(
!managerOptions.enableSetup,
Expand Down Expand Up @@ -101,7 +102,7 @@ export function makeXsSubprocessFactory({
}

// start the worker and establish a connection
const worker = await startXSnap(`${vatID}:${name}`, handleCommand);
const worker = await startXSnap(`${vatID}:${name}`, handleCommand, metered);

/** @type { (item: Tagged) => Promise<CrankResults> } */
async function issueTagged(item) {
Expand Down
30 changes: 29 additions & 1 deletion packages/SwingSet/test/test-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@
import { test } from '../tools/prepare-test-env-ava';

import path from 'path';
import { spawn } from 'child_process';
import { initSwingStore } from '@agoric/swing-store-simple';
import { buildVatController, loadBasedir } from '../src/index';
import {
buildVatController,
loadBasedir,
makeSwingsetController,
} from '../src/index';
import { initializeSwingset } from '../src/initializeSwingset';
import { checkKT } from './util';

function capdata(body, slots = []) {
Expand Down Expand Up @@ -117,6 +123,28 @@ test('XS bootstrap', async t => {
);
});

test('static vats are unmetered on XS', async t => {
const hostStorage = initSwingStore().storage;
const config = await loadBasedir(
path.resolve(__dirname, 'basedir-controller-2'),
);
config.defaultManagerType = 'xs-worker';
await initializeSwingset(config, [], hostStorage);
const limited = [];
const c = await makeSwingsetController(
hostStorage,
{},
{
spawn(command, args, options) {
limited.push(args.includes('-l'));
return spawn(command, args, options);
},
},
);
t.deepEqual(c.dump().log, ['bootstrap called']);
t.deepEqual(limited, [false, false, false]);
});

test('validate config.defaultManagerType', async t => {
const config = await loadBasedir(
path.resolve(__dirname, 'basedir-controller-2'),
Expand Down
16 changes: 16 additions & 0 deletions packages/xsnap/test/test-xs-perf.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ test('meter details', async t => {
t.is(meterType, 'xs-meter-7');
});

test('meter details are still available with no limit', async t => {
const opts = options();
const vat = xsnap({ ...opts, meteringLimit: 0 });
t.teardown(() => vat.terminate());
const result = await vat.evaluate(`
for (ix = 0; ix < 200; ix++) {
}
`);
const { meterUsage: meters } = result;
t.log(meters);
t.is(typeof meters.compute, 'number');
t.is(typeof meters.allocate, 'number');
t.true(meters.compute > 0);
t.true(meters.allocate > 0);
});

test('high resolution timer', async t => {
const opts = options();
const vat = xsnap(opts);
Expand Down

0 comments on commit 84fa8c9

Please sign in to comment.