Add requestAnimationFrame-based measurement method. (#173)

This PR adds a new query string parameter requestAnimationFrame, which takes
the value of either "timer" or "raf". "timer" is the existing and default
measurement method. When it's "raf", we use two consecutive requestAnimationFrame
first of which runs the sync step and second of which schedules a 0s timer to
signify the end of async step.
This commit is contained in:
Ryosuke Niwa 2023-05-24 11:50:11 -07:00 committed by GitHub
parent 34c169c724
commit a876f0e419
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 5 deletions

View file

@ -173,7 +173,7 @@ const WarmupSuite = {
],
};
class TestInvoker {
class TimerTestInvoker {
constructor(syncCallback, asyncCallback, reportCallback) {
this._syncCallback = syncCallback;
this._asyncCallback = asyncCallback;
@ -196,6 +196,29 @@ class TestInvoker {
}
}
class RAFTestInvoker {
constructor(syncCallback, asyncCallback, reportCallback) {
this._syncCallback = syncCallback;
this._asyncCallback = asyncCallback;
this._reportCallback = reportCallback;
}
start() {
return new Promise((resolve) => {
requestAnimationFrame(() => this._syncCallback());
requestAnimationFrame(() => {
setTimeout(() => {
this._asyncCallback();
setTimeout(async () => {
await this._reportCallback();
resolve();
}, 0);
}, 0);
});
});
}
}
export class BenchmarkRunner {
constructor(suites, client) {
this._suites = suites;
@ -327,7 +350,8 @@ export class BenchmarkRunner {
performance.measure(`${suite.name}.${test.name}-async`, asyncStartLabel, asyncEndLabel);
}
const report = () => this._recordTestResults(suite, test, syncTime, asyncTime);
const invoker = new TestInvoker(runSync, measureAsync, report);
const invokerClass = params.measurementMethod === 'raf' ? RAFTestInvoker : TimerTestInvoker;
const invoker = new invokerClass(runSync, measureAsync, report);
return invoker.start();
}

View file

@ -8,6 +8,7 @@ class Params {
iterationCount = 10;
suites = [];
useWarmupSuite = false;
measurementMethod = 'timer';
constructor(searchParams = undefined) {
if (searchParams)
@ -46,14 +47,22 @@ class Params {
}
this.developerMode = searchParams.has("developerMode");
searchParams.delete("developerMode");
const unused = Array.from(searchParams.keys());
if (unused.length > 0)
console.error("Got unused search params", unused);
if (searchParams.has("useWarmupSuite")) {
this.useWarmupSuite = true;
searchParams.delete("useWarmupSuite");
}
if (searchParams.has("measurementMethod")) {
this.measurementMethod = searchParams.get("measurementMethod");
if (this.measurementMethod !== 'timer' && this.measurementMethod !== 'raf')
throw new Error(`Invalid measurement method: ${this.measurementMethod}`);
searchParams.delete("measurementMethod");
}
const unused = Array.from(searchParams.keys());
if (unused.length > 0)
console.error("Got unused search params", unused);
}
toSearchParams() {