Skip to content

Commit

Permalink
feat(xsnap): high resolution timer: performance.now()
Browse files Browse the repository at this point in the history
  • Loading branch information
dckc authored and kriskowal committed May 4, 2021
1 parent eff98b4 commit 10940f9
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 39 deletions.
18 changes: 17 additions & 1 deletion packages/xsnap/src/xsnap.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static void fx_gc(xsMachine* the);
// static void fx_isPromiseJobQueueEmpty(xsMachine* the);
static void fx_markTimer(txMachine* the, void* it, txMarkRoot markRoot);
static void fx_print(xsMachine* the);
static void fx_performance_now(xsMachine* the);
static void fx_setImmediate(txMachine* the);
// static void fx_setInterval(txMachine* the);
// static void fx_setTimeout(txMachine* the);
Expand All @@ -80,13 +81,14 @@ static char* fxWriteNetStringError(int code);
// The order of the callbacks materially affects how they are introduced to
// code that runs from a snapshot, so must be consistent in the face of
// upgrade.
#define mxSnapshotCallbackCount 5
#define mxSnapshotCallbackCount 6
txCallback gxSnapshotCallbacks[mxSnapshotCallbackCount] = {
fx_issueCommand, // 0
fx_Array_prototype_meter, // 1
fx_print, // 2
fx_setImmediate, // 3
fx_gc, // 4
fx_performance_now, // 5
// fx_evalScript,
// fx_isPromiseJobQueueEmpty,
// fx_setInterval,
Expand Down Expand Up @@ -552,6 +554,12 @@ void fxBuildAgent(xsMachine* the)
// slot = fxNextHostFunctionProperty(the, slot, fx_setInterval, 1, xsID("setInterval"), XS_DONT_ENUM_FLAG);
// slot = fxNextHostFunctionProperty(the, slot, fx_setTimeout, 1, xsID("setTimeout"), XS_DONT_ENUM_FLAG);

mxPush(mxObjectPrototype);
txSlot* performance = fxLastProperty(the, fxNewObjectInstance(the));
fxNextHostFunctionProperty(the, performance, fx_performance_now, 1, xsID("now"), XS_DONT_ENUM_FLAG);
slot = fxNextSlotProperty(the, slot, the->stack, xsID("performance"), XS_DONT_ENUM_FLAG);
mxPop();

// mxPush(mxObjectPrototype);
// fxNextHostFunctionProperty(the, fxLastProperty(the, fxNewObjectInstance(the)), fx_print, 1, xsID("log"), XS_DONT_ENUM_FLAG);
// slot = fxNextSlotProperty(the, slot, the->stack, xsID("console"), XS_DONT_ENUM_FLAG);
Expand Down Expand Up @@ -1526,6 +1534,14 @@ void fxFreeSlots(txMachine* the, void* theSlots)
c_free(theSlots);
}

void fx_performance_now(txMachine *the)
{
c_timeval tv;
c_gettimeofday(&tv, NULL);
mxResult->kind = XS_NUMBER_KIND;
mxResult->value.number = (double)(tv.tv_sec * 1000.0) + ((double)(tv.tv_usec) / 1000.0);
}


// Local Variables:
// tab-width: 4
Expand Down
56 changes: 56 additions & 0 deletions packages/xsnap/test/test-xs-perf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import test from 'ava';
import { xsnap } from '../src/xsnap';
import { options } from './test-xsnap';

test('meter details', async t => {
const opts = options();
const vat = xsnap(opts);
t.teardown(() => vat.terminate());
const result = await vat.evaluate(`
let m = new Map();
let s1 = new Set();
for (ix = 0; ix < 20000; ix++) {
m.set(ix, 'garbage');
s1.add(ix);
}
for (ix = 0; ix < 20000; ix++) {
m.delete(ix);
s1.delete(ix);
}
`);
const {
meterUsage: { meterType, ...meters },
} = result;
t.log(meters);
const { entries, fromEntries } = Object;
t.deepEqual(
{
compute: 'number',
allocate: 'number',
allocateChunksCalls: 'number',
allocateSlotsCalls: 'number',
garbageCollectionCount: 'number',
mapSetAddCount: 'number',
mapSetRemoveCount: 'number',
maxBucketSize: 'number',
},
fromEntries(entries(meters).map(([p, v]) => [p, typeof v])),
);
t.is(meterType, 'xs-meter-6');
});

test('high resolution timer', async t => {
const opts = options();
const vat = xsnap(opts);
t.teardown(() => vat.terminate());
await vat.evaluate(`
const send = it => issueCommand(ArrayBuffer.fromString(JSON.stringify(it)));
const t = performance.now();
send(t);
`);
const [milliseconds] = opts.messages.map(JSON.parse);
t.log({ milliseconds, date: new Date(milliseconds) });
t.is('number', typeof milliseconds);
});
39 changes: 1 addition & 38 deletions packages/xsnap/test/test-xsnap.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const xsnapOptions = {
stdout: 'inherit',
};

function options() {
export function options() {
const messages = [];
async function handleCommand(message) {
messages.push(decoder.decode(message));
Expand Down Expand Up @@ -505,40 +505,3 @@ test('property name space exhaustion: orderly fail-stop', async t => {
});
}
})();

test('meter details', async t => {
const opts = options();
const vat = xsnap(opts);
t.teardown(() => vat.terminate());
const result = await vat.evaluate(`
let m = new Map();
let s1 = new Set();
for (ix = 0; ix < 20000; ix++) {
m.set(ix, 'garbage');
s1.add(ix);
}
for (ix = 0; ix < 20000; ix++) {
m.delete(ix);
s1.delete(ix);
}
`);
const {
meterUsage: { meterType, ...meters },
} = result;
t.log(meters);
const { entries, fromEntries } = Object;
t.deepEqual(
{
compute: 'number',
allocate: 'number',
allocateChunksCalls: 'number',
allocateSlotsCalls: 'number',
garbageCollectionCount: 'number',
mapSetAddCount: 'number',
mapSetRemoveCount: 'number',
maxBucketSize: 'number',
},
fromEntries(entries(meters).map(([p, v]) => [p, typeof v])),
);
t.is(meterType, 'xs-meter-6');
});

0 comments on commit 10940f9

Please sign in to comment.