|
1 | 1 | import { Metric } from "./metric.mjs";
|
2 | 2 | import { params } from "./params.mjs";
|
3 |
| -import { TEST_INVOKER_LOOKUP } from "./test-invoker.mjs"; |
| 3 | +import { SUITE_RUNNER_LOOKUP } from "./suite-runner.mjs"; |
4 | 4 |
|
5 | 5 | const performance = globalThis.performance;
|
6 | 6 |
|
@@ -223,7 +223,7 @@ function geomeanToScore(geomean) {
|
223 | 223 | // The WarmupSuite is used to make sure all runner helper functions and
|
224 | 224 | // classes are compiled, to avoid unnecessary pauses due to delayed
|
225 | 225 | // compilation of runner methods in the middle of the measuring cycle.
|
226 |
| -const WarmupSuite = { |
| 226 | +export const WarmupSuite = { |
227 | 227 | name: "Warmup",
|
228 | 228 | url: "warmup/index.html",
|
229 | 229 | async prepare(page) {
|
@@ -410,7 +410,7 @@ export class BenchmarkRunner {
|
410 | 410 | // FIXME: Encapsulate more state in the SuiteRunner.
|
411 | 411 | // FIXME: Return and use measured values from SuiteRunner.
|
412 | 412 | const suiteRunnerClass = SUITE_RUNNER_LOOKUP[suite.type ?? "default"];
|
413 |
| - const suiteRunner = new suiteRunnerClass(this._measuredValues, this._frame, this._page, this._client, suite); |
| 413 | + const suiteRunner = new suiteRunnerClass(this._frame, this._page, params, suite, this._client, this._measuredValues); |
414 | 414 | await suiteRunner.run();
|
415 | 415 | }
|
416 | 416 |
|
@@ -484,151 +484,3 @@ export class BenchmarkRunner {
|
484 | 484 | metric.computeAggregatedMetrics();
|
485 | 485 | }
|
486 | 486 | }
|
487 |
| - |
488 |
| -// FIXME: Create AsyncSuiteRunner subclass. |
489 |
| -// FIXME: Create RemoteSuiteRunner subclass. |
490 |
| -export class SuiteRunner { |
491 |
| - constructor(measuredValues, frame, page, client, suite) { |
492 |
| - // FIXME: Create SuiteRunner-local measuredValues. |
493 |
| - this._suiteResults = measuredValues.tests[suite.name]; |
494 |
| - if (!this._suiteResults) { |
495 |
| - this._suiteResults = { tests: {}, total: 0 }; |
496 |
| - measuredValues.tests[suite.name] = this._suiteResults; |
497 |
| - } |
498 |
| - this._measuredValues = measuredValues; |
499 |
| - this._frame = frame; |
500 |
| - this._page = page; |
501 |
| - this._client = client; |
502 |
| - this._suite = suite; |
503 |
| - } |
504 |
| - |
505 |
| - async run() { |
506 |
| - await this._prepareSuite(); |
507 |
| - await this._runSuite(); |
508 |
| - } |
509 |
| - |
510 |
| - async _prepareSuite() { |
511 |
| - const suiteName = this._suite.name; |
512 |
| - const suitePrepareStartLabel = `suite-${suiteName}-prepare-start`; |
513 |
| - const suitePrepareEndLabel = `suite-${suiteName}-prepare-end`; |
514 |
| - |
515 |
| - performance.mark(suitePrepareStartLabel); |
516 |
| - await this._loadFrame(); |
517 |
| - await this._suite.prepare(this._page); |
518 |
| - performance.mark(suitePrepareEndLabel); |
519 |
| - |
520 |
| - performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel); |
521 |
| - } |
522 |
| - |
523 |
| - async _runSuite() { |
524 |
| - const suiteName = this._suite.name; |
525 |
| - const suiteStartLabel = `suite-${suiteName}-start`; |
526 |
| - const suiteEndLabel = `suite-${suiteName}-end`; |
527 |
| - |
528 |
| - performance.mark(suiteStartLabel); |
529 |
| - for (const test of this._suite.tests) |
530 |
| - await this._runTestAndRecordResults(test); |
531 |
| - performance.mark(suiteEndLabel); |
532 |
| - |
533 |
| - performance.measure(`suite-${suiteName}`, suiteStartLabel, suiteEndLabel); |
534 |
| - this._validateSuiteTotal(); |
535 |
| - } |
536 |
| - |
537 |
| - _validateSuiteTotal() { |
538 |
| - // When the test is fast and the precision is low (for example with Firefox' |
539 |
| - // privacy.resistFingerprinting preference), it's possible that the measured |
540 |
| - // total duration for an entire is 0. |
541 |
| - const suiteTotal = this._suiteResults.total; |
542 |
| - if (suiteTotal === 0) |
543 |
| - throw new Error(`Got invalid 0-time total for suite ${this._suite.name}: ${suiteTotal}`); |
544 |
| - } |
545 |
| - |
546 |
| - async _loadFrame() { |
547 |
| - return new Promise((resolve, reject) => { |
548 |
| - const frame = this._page._frame; |
549 |
| - frame.onload = () => resolve(); |
550 |
| - frame.onerror = () => reject(); |
551 |
| - frame.src = this._suite.url; |
552 |
| - }); |
553 |
| - } |
554 |
| - |
555 |
| - async _runTestAndRecordResults(test) { |
556 |
| - if (this._client?.willRunTest) |
557 |
| - await this._client.willRunTest(this._suite, test); |
558 |
| - |
559 |
| - // Prepare all mark labels outside the measuring loop. |
560 |
| - const suiteName = this._suite.name; |
561 |
| - const testName = test.name; |
562 |
| - const startLabel = `${suiteName}.${testName}-start`; |
563 |
| - const syncEndLabel = `${suiteName}.${testName}-sync-end`; |
564 |
| - const asyncStartLabel = `${suiteName}.${testName}-async-start`; |
565 |
| - const asyncEndLabel = `${suiteName}.${testName}-async-end`; |
566 |
| - |
567 |
| - let syncTime; |
568 |
| - let asyncStartTime; |
569 |
| - let asyncTime; |
570 |
| - const runSync = () => { |
571 |
| - if (params.warmupBeforeSync) { |
572 |
| - performance.mark("warmup-start"); |
573 |
| - const startTime = performance.now(); |
574 |
| - // Infinite loop for the specified ms. |
575 |
| - while (performance.now() - startTime < params.warmupBeforeSync) |
576 |
| - continue; |
577 |
| - performance.mark("warmup-end"); |
578 |
| - } |
579 |
| - performance.mark(startLabel); |
580 |
| - const syncStartTime = performance.now(); |
581 |
| - test.run(this._page); |
582 |
| - const syncEndTime = performance.now(); |
583 |
| - performance.mark(syncEndLabel); |
584 |
| - |
585 |
| - syncTime = syncEndTime - syncStartTime; |
586 |
| - |
587 |
| - performance.mark(asyncStartLabel); |
588 |
| - asyncStartTime = performance.now(); |
589 |
| - }; |
590 |
| - const measureAsync = () => { |
591 |
| - // Some browsers don't immediately update the layout for paint. |
592 |
| - // Force the layout here to ensure we're measuring the layout time. |
593 |
| - const height = this._frame.contentDocument.body.getBoundingClientRect().height; |
594 |
| - const asyncEndTime = performance.now(); |
595 |
| - asyncTime = asyncEndTime - asyncStartTime; |
596 |
| - this._frame.contentWindow._unusedHeightValue = height; // Prevent dead code elimination. |
597 |
| - performance.mark(asyncEndLabel); |
598 |
| - if (params.warmupBeforeSync) |
599 |
| - performance.measure("warmup", "warmup-start", "warmup-end"); |
600 |
| - const suiteName = this._suite.name; |
601 |
| - const testName = test.name; |
602 |
| - performance.measure(`${suiteName}.${testName}-sync`, startLabel, syncEndLabel); |
603 |
| - performance.measure(`${suiteName}.${testName}-async`, asyncStartLabel, asyncEndLabel); |
604 |
| - }; |
605 |
| - |
606 |
| - const report = () => this._recordTestResults(test, syncTime, asyncTime); |
607 |
| - const invokerClass = TEST_INVOKER_LOOKUP[params.measurementMethod]; |
608 |
| - const invoker = new invokerClass(runSync, measureAsync, report, params); |
609 |
| - |
610 |
| - return invoker.start(); |
611 |
| - } |
612 |
| - |
613 |
| - async _recordTestResults(test, syncTime, asyncTime) { |
614 |
| - // Skip reporting updates for the warmup suite. |
615 |
| - if (this._suite === WarmupSuite) |
616 |
| - return; |
617 |
| - |
618 |
| - const total = syncTime + asyncTime; |
619 |
| - this._suiteResults.tests[test.name] = { tests: { Sync: syncTime, Async: asyncTime }, total: total }; |
620 |
| - this._suiteResults.total += total; |
621 |
| - |
622 |
| - if (this._client?.didRunTest) |
623 |
| - await this._client.didRunTest(this._suite, test); |
624 |
| - } |
625 |
| -} |
626 |
| - |
627 |
| -// FIXME: implement remote steps |
628 |
| -class RemoteSuiteRunner extends SuiteRunner {} |
629 |
| - |
630 |
| -const SUITE_RUNNER_LOOKUP = { |
631 |
| - __proto__: null, |
632 |
| - default: SuiteRunner, |
633 |
| - remote: RemoteSuiteRunner, |
634 |
| -}; |
0 commit comments