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

Open
wants to merge 30 commits into
base: main
Choose a base branch
from

Conversation

flashdesignory
Copy link
Contributor

@flashdesignory flashdesignory commented Nov 20, 2024

As discussed in our sync, here is a combination of the AsyncRunner and Message Channel pr.

Relevant code snippet (udpated):

class AsyncRAFTestInvoker extends BaseRAFTestInvoker {
    static mc = new MessageChannel();
    _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();
            gotPromise = true;
            tryTriggerAsyncCallback();
        });

        requestAnimationFrame(() => {
            setTimeout(() => {
                gotTimer = true;
                tryTriggerAsyncCallback();
            });

            AsyncRAFTestInvoker.mc.port1.addEventListener(
                "message",
                function () {
                    gotMessage = true;
                    tryTriggerAsyncCallback();
                },
                { once: true }
            );
            AsyncRAFTestInvoker.mc.port1.start();
            AsyncRAFTestInvoker.mc.port2.postMessage("speedometer");
        });
    }
}

For testing purposes I kept an explicit type of "async" in the test file, but I opted all default suites into using it.

Initial testing shows that it should also fix the react specific issue.

Other issue solved by this pr: #83

@flashdesignory flashdesignory marked this pull request as ready for review November 21, 2024 02:15
resources/tests.mjs Outdated Show resolved Hide resolved
resources/tests.mjs Outdated Show resolved Hide resolved
@flashdesignory
Copy link
Contributor Author

Can we split the change to remove measurementMethod into a separate PR? We should also update params.mjs and developer-mode.mjs.

ok, reverted for now. I agree a cleanup pr to remove this would be better.

@bgrins
Copy link
Contributor

bgrins commented Dec 17, 2024

@smaug---- I pushed this to https://feature-async-runner-message-channel--speedometer-preview.netlify.app/ for anyone who wants to test.

@@ -75,7 +75,8 @@ 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 testRunnerClass = TEST_RUNNER_LOOKUP[this.#suite.type ?? "default"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of changing the test runner based on the suite type for some suites, can we initially add a toggle to developer menu so that we can try out async runner?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my understanding the agreement in the meeting was to unconditionally enable the new runner for the preact workloads and add the global developer-mode menu in a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct - below is the list on enabled suites (for now):

  • TodoMVC-React-Complex-DOM,
  • TodoMVC-React-Redux,
  • TodoMVC-Preact-Complex-DOM, (technically not react based, but it's similar)
  • NewsSite-Next,
  • React-Stockcharts-SVG

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're doing that, we need before/after numbers across browsers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll run crossbench for the ones on the list and post results here.

Copy link
Contributor Author

@flashdesignory flashdesignory Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are metrics for the next.js workload:
Screenshot 2024-12-18 at 5 54 40 PM

Copy link
Member

@rniwa rniwa Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So Safari's total time goes up while the total time for Chrome & Firefox both go down? With that kind of magnitude of a difference, we need a much more thorough investigation before we can approve of the change. I suggest we land this method initially as an optional developer-menu only feature instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add an option for the developer menu 👍

@rniwa rniwa added the major change A change with major implications on benchmark results or affect governance policy label Dec 18, 2024
Copy link

@smaug---- smaug---- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable

@flashdesignory flashdesignory force-pushed the feature/async-runner-message-channel branch from fd6dd12 to 110c94a Compare December 20, 2024 18:38
@flashdesignory
Copy link
Contributor Author

@rniwa - I believe we addressed all the comments. Anything else missing that I can help with?

};

requestAnimationFrame(async () => {
await this._syncCallback();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit suspicious to alway trigger the workload in rAF in this asynchronous measurement method.
A real web apps don't necessarily always wait for rAF to trigger any work so for the maximal realism, it might be better if we just triggered sync callback at a pseudo-random time relative to rAF.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean just rmaking _scheduleCallbacks async and removing this raf here?


requestAnimationFrame(() => {
setTimeout(() => {
gotTimer = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think we need to wait for any promises scheduled in setTimeout get resolved so I think we need an await here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what we are awaiting here, since that just runs the check-in function tryTriggerAsyncCallback in the setTimeout. Would you mind giving me an example of what you had in mind?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is to do this:

await Promise.resolve();

This will ensure that any promises scheduled during setTimeout will get resolved before we set gotTimer to true.

"message",
function () {
gotMessage = true;
tryTriggerAsyncCallback();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here. I think we need to wait for any promises that got scheduled as a result of postMessage to get processed before we finish the measurement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: code example would help, which I assume would be similar to above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major change A change with major implications on benchmark results or affect governance policy
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants