Skip to content
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

Async Runner with Message Channel #458

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b594115
git branch
flashdesignory Oct 30, 2024
f154a4c
initial change
flashdesignory Oct 30, 2024
9459c00
add event
flashdesignory Oct 31, 2024
d462764
add comment
flashdesignory Oct 31, 2024
d037f89
rollback requestIdleCallback
flashdesignory Oct 31, 2024
79f8450
run format
flashdesignory Oct 31, 2024
14f1f6d
undo newssite changes
flashdesignory Oct 31, 2024
d08606d
remove test test
flashdesignory Nov 8, 2024
4540937
Merge branch 'main' into feature/async-runner
flashdesignory Nov 13, 2024
a02d7cc
merge main
flashdesignory Nov 13, 2024
5281af4
Merge branch 'main' into feature/async-runner
flashdesignory Nov 13, 2024
d4fa570
Merge branch 'main' into feature/async-runner
flashdesignory Nov 15, 2024
764b61b
cleanup
flashdesignory Nov 15, 2024
ace8c3b
reset news site build files
flashdesignory Nov 15, 2024
147c38f
initial refactor
flashdesignory Nov 20, 2024
92f9024
Merge branch 'main' into feature/async-runner-message-channel
flashdesignory Dec 10, 2024
7cca4e0
pr feedback
flashdesignory Dec 10, 2024
2b92c1f
remove async from next.js steps
flashdesignory Dec 11, 2024
acc7522
use static Message Channel
flashdesignory Dec 11, 2024
c778807
Merge branch 'main' into feature/async-runner-message-channel
flashdesignory Dec 17, 2024
211ba6a
cleanup
flashdesignory Dec 17, 2024
81b815e
cleanup test-runner
flashdesignory Dec 18, 2024
37ffb46
fix tests
flashdesignory Dec 18, 2024
63910a3
only opt in react based workloads
flashdesignory Dec 18, 2024
6b6f8d4
remove label getters
flashdesignory Dec 18, 2024
110c94a
Merge branch 'main' into feature/async-runner-message-channel
flashdesignory Dec 20, 2024
a8a4059
Merge branch 'main' into feature/async-runner-message-channel
flashdesignory Jan 7, 2025
05ce8bf
fix bad merge
flashdesignory Jan 7, 2025
930472c
add developer menu option for async type
flashdesignory Jan 7, 2025
4b69e1d
run format
flashdesignory Jan 7, 2025
16dec03
await promises
flashdesignory Jan 14, 2025
9a66132
remove opt-ins to async runner
flashdesignory Jan 14, 2025
daf60ab
remove console
flashdesignory Jan 14, 2025
ac0b4e0
Merge branch 'main' into feature/async-runner-message-channel
flashdesignory Jan 14, 2025
69350a9
rebuild next
flashdesignory Jan 14, 2025
064e1cc
fix params and pr feedback
flashdesignory Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion resources/benchmark-runner.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ export class BenchmarkRunner {
async runSuite(suite) {
// FIXME: Encapsulate more state in the SuiteRunner.
// FIXME: Return and use measured values from SuiteRunner.
const suiteRunnerClass = SUITE_RUNNER_LOOKUP[suite.type ?? "default"];
const type = suite.type ?? ((params.useAsyncSteps && "async") || "default");
const suiteRunnerClass = SUITE_RUNNER_LOOKUP[type];
const suiteRunner = new suiteRunnerClass(this._frame, this._page, params, suite, this._client, this._measuredValues);
await suiteRunner.run();
}
Expand Down
9 changes: 8 additions & 1 deletion resources/developer-mode.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function createDeveloperModeContainer() {
settings.append(createUIForWarmupSuite());
settings.append(createUIForWarmupBeforeSync());
settings.append(createUIForSyncStepDelay());
settings.append(createUIForAsyncSteps());

content.append(document.createElement("hr"));
content.append(settings);
Expand All @@ -45,6 +46,12 @@ function createUIForWarmupSuite() {
});
}

function createUIForAsyncSteps() {
return createCheckboxUI("Use Async Steps", params.useAsyncSteps, (isChecked) => {
params.useAsyncSteps = isChecked;
});
}

function createCheckboxUI(labelValue, initialValue, paramsUpdateCallback) {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
Expand Down Expand Up @@ -255,7 +262,7 @@ function updateURL() {
}
}

const defaultParamKeys = ["iterationCount", "useWarmupSuite", "warmupBeforeSync", "waitBeforeSync"];
const defaultParamKeys = ["iterationCount", "useWarmupSuite", "warmupBeforeSync", "waitBeforeSync", "useAsyncSteps"];
for (const paramKey of defaultParamKeys) {
if (params[paramKey] !== defaultParams[paramKey])
url.searchParams.set(paramKey, params[paramKey]);
Expand Down
2 changes: 1 addition & 1 deletion resources/newssite/news-next/dist/404.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="./_next/static/css/a0dca1379a01e5cf.css" as="style"/><link rel="stylesheet" href="./_next/static/css/a0dca1379a01e5cf.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="./_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="./_next/static/chunks/webpack-e50e9853db18b759.js" defer=""></script><script src="./_next/static/chunks/framework-2c79e2a64abdb08b.js" defer=""></script><script src="./_next/static/chunks/main-2ba37e62325cc71b.js" defer=""></script><script src="./_next/static/chunks/pages/_app-4fe6038a10d156ec.js" defer=""></script><script src="./_next/static/chunks/pages/_error-54de1933a164a1ff.js" defer=""></script><script src="./_next/static/slmX88Sy3MO0SLK8cVHnz/_buildManifest.js" defer=""></script><script src="./_next/static/slmX88Sy3MO0SLK8cVHnz/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><div id="settings-container"></div><div id="notifications-container"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"slmX88Sy3MO0SLK8cVHnz","assetPrefix":".","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="./_next/static/css/a0dca1379a01e5cf.css" as="style"/><link rel="stylesheet" href="./_next/static/css/a0dca1379a01e5cf.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="./_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="./_next/static/chunks/webpack-e50e9853db18b759.js" defer=""></script><script src="./_next/static/chunks/framework-2c79e2a64abdb08b.js" defer=""></script><script src="./_next/static/chunks/main-2ba37e62325cc71b.js" defer=""></script><script src="./_next/static/chunks/pages/_app-77983e68be50f72a.js" defer=""></script><script src="./_next/static/chunks/pages/_error-54de1933a164a1ff.js" defer=""></script><script src="./_next/static/dKI4-ZnFPRMFEw-AlcuLr/_buildManifest.js" defer=""></script><script src="./_next/static/dKI4-ZnFPRMFEw-AlcuLr/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><div id="settings-container"></div><div id="notifications-container"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"dKI4-ZnFPRMFEw-AlcuLr","assetPrefix":".","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>

This file was deleted.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

This file was deleted.

Large diffs are not rendered by default.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

2 changes: 1 addition & 1 deletion resources/newssite/news-next/dist/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="./_next/static/css/a0dca1379a01e5cf.css" as="style"/><link rel="stylesheet" href="./_next/static/css/a0dca1379a01e5cf.css" data-n-g=""/><link rel="preload" href="./_next/static/css/69253d842fd3fbfd.css" as="style"/><link rel="stylesheet" href="./_next/static/css/69253d842fd3fbfd.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="./_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="./_next/static/chunks/webpack-e50e9853db18b759.js" defer=""></script><script src="./_next/static/chunks/framework-2c79e2a64abdb08b.js" defer=""></script><script src="./_next/static/chunks/main-2ba37e62325cc71b.js" defer=""></script><script src="./_next/static/chunks/pages/_app-4fe6038a10d156ec.js" defer=""></script><script src="./_next/static/chunks/553-29fd8c03a09c7b37.js" defer=""></script><script src="./_next/static/chunks/pages/index-7052462c4e106c39.js" defer=""></script><script src="./_next/static/slmX88Sy3MO0SLK8cVHnz/_buildManifest.js" defer=""></script><script src="./_next/static/slmX88Sy3MO0SLK8cVHnz/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><div id="settings-container"></div><div id="notifications-container"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"slmX88Sy3MO0SLK8cVHnz","assetPrefix":".","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="./_next/static/css/a0dca1379a01e5cf.css" as="style"/><link rel="stylesheet" href="./_next/static/css/a0dca1379a01e5cf.css" data-n-g=""/><link rel="preload" href="./_next/static/css/2cf5163b53bb0adb.css" as="style"/><link rel="stylesheet" href="./_next/static/css/2cf5163b53bb0adb.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="./_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="./_next/static/chunks/webpack-e50e9853db18b759.js" defer=""></script><script src="./_next/static/chunks/framework-2c79e2a64abdb08b.js" defer=""></script><script src="./_next/static/chunks/main-2ba37e62325cc71b.js" defer=""></script><script src="./_next/static/chunks/pages/_app-77983e68be50f72a.js" defer=""></script><script src="./_next/static/chunks/743-fd706aeabb7828e3.js" defer=""></script><script src="./_next/static/chunks/pages/index-5268ea812327eb5e.js" defer=""></script><script src="./_next/static/dKI4-ZnFPRMFEw-AlcuLr/_buildManifest.js" defer=""></script><script src="./_next/static/dKI4-ZnFPRMFEw-AlcuLr/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><div id="settings-container"></div><div id="notifications-container"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"dKI4-ZnFPRMFEw-AlcuLr","assetPrefix":".","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
3 changes: 3 additions & 0 deletions resources/shared/params.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export class Params {
tags = [];
// Toggle running a dummy suite once before the normal test suites.
useWarmupSuite = false;
// toggle async type vs default raf type.
useAsyncSteps = false;
// Change how a test measurement is triggered and async time is measured:
// "timer": The classic (as in Speedometer 2.x) way using setTimeout
// "raf": Using rAF callbacks, both for triggering the sync part and for measuring async time.
Expand Down Expand Up @@ -50,6 +52,7 @@ export class Params {
this.tags = this._parseTags(searchParams);
this.developerMode = this._parseBooleanParam(searchParams, "developerMode");
this.useWarmupSuite = this._parseBooleanParam(searchParams, "useWarmupSuite");
this.useAsyncSteps = this._parseBooleanParam(searchParams, "useAsyncSteps");
this.waitBeforeSync = this._parseIntParam(searchParams, "waitBeforeSync", 0);
this.warmupBeforeSync = this._parseIntParam(searchParams, "warmupBeforeSync", 0);
this.measurementMethod = this._parseMeasurementMethod(searchParams);
Expand Down
51 changes: 50 additions & 1 deletion resources/shared/test-invoker.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TestInvoker {
}
}

export class RAFTestInvoker extends TestInvoker {
class BaseRAFTestInvoker extends TestInvoker {
start() {
return new Promise((resolve) => {
if (this._params.waitBeforeSync)
Expand All @@ -16,7 +16,9 @@ export class RAFTestInvoker extends TestInvoker {
this._scheduleCallbacks(resolve);
});
}
}

class RAFTestInvoker extends BaseRAFTestInvoker {
_scheduleCallbacks(resolve) {
requestAnimationFrame(() => this._syncCallback());
requestAnimationFrame(() => {
Expand All @@ -31,7 +33,54 @@ export class RAFTestInvoker extends TestInvoker {
}
}

class AsyncRAFTestInvoker extends BaseRAFTestInvoker {
static mc = new MessageChannel();
flashdesignory marked this conversation as resolved.
Show resolved Hide resolved
_scheduleCallbacks(resolve) {
let gotTimer = false;
let gotMessage = false;
let gotPromise = false;

const tryTriggerAsyncCallback = () => {
if (!gotTimer || !gotMessage || !gotPromise)
return;

this._asyncCallback();
setTimeout(async () => {
await this._reportCallback();
resolve();
}, 0);
};

requestAnimationFrame(async () => {
await this._syncCallback();
rniwa marked this conversation as resolved.
Show resolved Hide resolved
gotPromise = true;
tryTriggerAsyncCallback();
});

requestAnimationFrame(() => {
setTimeout(async () => {
await Promise.resolve();
gotTimer = true;
rniwa marked this conversation as resolved.
Show resolved Hide resolved
tryTriggerAsyncCallback();
});

AsyncRAFTestInvoker.mc.port1.addEventListener(
"message",
async function () {
await Promise.resolve();
gotMessage = true;
tryTriggerAsyncCallback();
rniwa marked this conversation as resolved.
Show resolved Hide resolved
},
{ once: true }
);
AsyncRAFTestInvoker.mc.port1.start();
AsyncRAFTestInvoker.mc.port2.postMessage("speedometer");
});
}
}

export const TEST_INVOKER_LOOKUP = {
__proto__: null,
raf: RAFTestInvoker,
async: AsyncRAFTestInvoker,
};
46 changes: 41 additions & 5 deletions resources/shared/test-runner.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,28 @@ export class TestRunner {
#suite;
#test;
#callback;
#type;

constructor(frame, page, params, suite, test, callback) {
constructor(frame, page, params, suite, test, callback, type) {
this.#suite = suite;
this.#test = test;
this.#params = params;
this.#callback = callback;

this.#page = page;
this.#frame = frame;
this.#type = type;
}

get page() {
return this.#page;
}

get test() {
return this.#test;
}

_runSyncStep(test, page) {
test.run(page);
}

async runTest() {
Expand All @@ -30,7 +43,7 @@ export class TestRunner {
let asyncStartTime;
let asyncTime;

const runSync = () => {
const runSync = async () => {
if (this.#params.warmupBeforeSync) {
performance.mark("warmup-start");
const startTime = performance.now();
Expand All @@ -41,7 +54,12 @@ export class TestRunner {
}
performance.mark(syncStartLabel);
const syncStartTime = performance.now();
this.#test.run(this.#page);

if (this.#type === "async")
await this._runSyncStep(this.test, this.page);
else
this._runSyncStep(this.test, this.page);

const mark = performance.mark(syncEndLabel);
const syncEndTime = mark.startTime;

Expand All @@ -68,9 +86,27 @@ export class TestRunner {
};

const report = () => this.#callback(this.#test, syncTime, asyncTime);
const invokerClass = TEST_INVOKER_LOOKUP[this.#params.measurementMethod];
const invokerType = this.#suite.type === "async" || this.#params.useAsyncSteps ? "async" : this.#params.measurementMethod;
const invokerClass = TEST_INVOKER_LOOKUP[invokerType];
const invoker = new invokerClass(runSync, measureAsync, report, this.#params);

return invoker.start();
}
}

export class AsyncTestRunner extends TestRunner {
constructor(frame, page, params, suite, test, callback, type) {
super(frame, page, params, suite, test, callback, type);
}

async _runSyncStep(test, page) {
await test.run(page);
}
}

export const TEST_RUNNER_LOOKUP = {
__proto__: null,
default: TestRunner,
async: AsyncTestRunner,
remote: TestRunner,
};
7 changes: 5 additions & 2 deletions resources/suite-runner.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TestRunner } from "./shared/test-runner.mjs";
import { TEST_RUNNER_LOOKUP } from "./shared/test-runner.mjs";
import { WarmupSuite } from "./benchmark-runner.mjs";

export class SuiteRunner {
Expand Down Expand Up @@ -75,7 +75,9 @@ export class SuiteRunner {
if (this.#client?.willRunTest)
await this.#client.willRunTest(this.#suite, test);

const testRunner = new TestRunner(this.#frame, this.#page, this.#params, this.#suite, test, this._recordTestResults);
const testRunnerType = this.#suite.type ?? this.params.useAsyncSteps ? "async" : "default";
const testRunnerClass = TEST_RUNNER_LOOKUP[testRunnerType];
const testRunner = new testRunnerClass(this.#frame, this.#page, this.#params, this.#suite, test, this._recordTestResults, testRunnerType);
await testRunner.runTest();
}
performance.mark(suiteEndLabel);
Expand Down Expand Up @@ -214,5 +216,6 @@ export class RemoteSuiteRunner extends SuiteRunner {
export const SUITE_RUNNER_LOOKUP = {
__proto__: null,
default: SuiteRunner,
async: SuiteRunner,
remote: RemoteSuiteRunner,
};