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

Remote Runner / PostMessge api #456

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

Conversation

flashdesignory
Copy link
Contributor

@flashdesignory flashdesignory commented Nov 19, 2024

This pr introduces Remote Runner workloads.
Workloads that are local OR that point to a remote url (when running Speedometer locally), can communicate and run their own tests via PostMessage.

Basic flow:

  1. SuiteRunner loads the iframe of the local or remote workload.
  2. SuiteRunner waits for the "app-ready" message from the workload.
  3. Workload sends "app-ready" message, once its able to listen and receive a command to start the tests.
  4. SuiteRunner sends the "benchmark-suite" command to start the testing (with an optional suite name).
  5. Workload runs through the test suite and collects performance metrics.
  6. After each completed test step it sends a "step-complete" message, to update progress in speedometer.
  7. With the "suite-complete" message, the workload sends the metrics along.
  8. Speedometer receives metrics.

image

Notes

  • TestRunner and TestInvoker files are installed as dependencies in the news-site-next workload, to ensure they stay synced with updates.

window.version = "1.0.0";

/** **********************************************************************
* Params
Copy link
Contributor

Choose a reason for hiding this comment

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

@flashdesignory I don't see the following logic used in the main runner. Since it also reads params from the URL, would it be possible to share some code here instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've shared params.mjs in the other example 728aeab

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we could - the params.mjs is slightly different, but I can take a look at both and see if I can clean up and reuse

@bgrins
Copy link
Contributor

bgrins commented Nov 21, 2024

Now that this has mostly incorporated #459 (I'd still like to see the params sharing) I think it's going to be easier to review & hopefully get landed for testing @rniwa @julienw

Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

I haven't tried locally but this looks pretty good to me. We can always fix things later if there's anything broken anyway.

r+ with my comments fixed.

Note: it would be a lot easier to review if you'd reworked the PR to have consistent commits, for example:

Commit 1: move files around without changing them, just update the references in other files
Commit 2: add the remote runner + the workload tools
Commit 3: change the workload itself

If you do this for future complex PR this will make them a joy to review (and hence faster to review as well). Thanks!


export default function App() {
useLayoutEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add a comment explaining why you chose useLayoutEffect over useEffect?


export default function App() {
useLayoutEffect(() => {
connectToBenchmark(getBenchmarkSuitesManager(), "news-next", 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

I admit I haven't followed closely, but do we need to disconnect when it's unmounted?

@@ -0,0 +1,41 @@
import { BenchmarkTestStep, BenchmarkTestSuite, BenchmarkSuitesManager, forceLayout, getElement } from "speedometer-utils/workload-testing-utils.mjs";
Copy link
Contributor

Choose a reason for hiding this comment

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

oh I so want #371 to be merged finally

Comment on lines +139 to +143
// FIXME: use this._suite in all SuiteRunner methods directly.
await this._prepareSuite();
await this._runSuite();

window.removeEventListener("message", handler);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: put that in a try/finally so that we remove the event listener even if there's an exception

Comment on lines +26 to +49
get frame() {
return this.#frame;
}

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

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

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

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

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

Copy link
Contributor

Choose a reason for hiding this comment

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

frankly all these private variables look superfluous to me, I'd rather put everything public, but well I'm not opposed either.

Comment on lines +91 to +92
* Various methods that are extracted from the Page class.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

could the Page class use them directly (maybe as a follow-up, I don't know)
I don't feel comfortable with the duplication.

performance.mark(suitePrepareStartLabel);

// Wait for the app-ready message from the workload.
const promise = this._subscribeOnce("app-ready");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const promise = this._subscribeOnce("app-ready");
const appReadyPromise = this._subscribeOnce("app-ready");

Comment on lines +175 to +176
this.suiteResults.tests = response.result.tests;
this.suiteResults.total += response.result.total;
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we overriding the tests property but incrementing the total value?
Should we append the tests instead?
(I haven't researched closely but it would be good to comment about that)

@@ -146,21 +146,25 @@ class Params {
return shuffleSeed;
}

toSearchParams() {
toSearchParams(forRemote = false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we have an option object parameter instead of a boolean? it's really not clear what this does from the caller site.

(and actually from here neither, a comment would be nice)

return new URLSearchParams(rawParams).toString();
}
}

export const defaultParams = new Params();

const searchParams = new URLSearchParams(window.location.search);
const searchParams = new URLSearchParams(typeof window !== "undefined" ? window.location.search : undefined);
Copy link
Contributor

Choose a reason for hiding this comment

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

when is it happening that window isn't present?

optional nit: use ?. operator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants