Skip to content

Commit b4cc88a

Browse files
committed
Merge branch 'main' of github.com:camillobruni/Speedometer into 2025-04-29_force_layout
2 parents 8baee34 + 0746a31 commit b4cc88a

8 files changed

Lines changed: 60 additions & 21 deletions

File tree

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ <h2>Non-standard Parameters</h2>
100100
</div>
101101
<div class="aggregated-metric-result">
102102
<h2>Aggregate Metric</h2>
103-
<div id="geomean-chart"></div>
103+
<div id="aggregate-chart"></div>
104104
<h2>Test Metrics Overview</h2>
105105
<div id="tests-chart"></div>
106106
</div>

resources/benchmark-runner.mjs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,10 @@ export class BenchmarkRunner {
470470

471471
_appendIterationMetrics() {
472472
const getMetric = (name, unit = "ms") => this._metrics[name] || (this._metrics[name] = new Metric(name, unit));
473-
const iterationTotalMetric = (i) => {
473+
const iterationMetric = (i, name) => {
474474
if (i >= params.iterationCount)
475475
throw new Error(`Requested iteration=${i} does not exist.`);
476-
return getMetric(`Iteration-${i}-Total`);
476+
return getMetric(`Iteration-${i}-${name}`);
477477
};
478478

479479
const collectSubMetrics = (prefix, items, parent) => {
@@ -498,20 +498,34 @@ export class BenchmarkRunner {
498498
// Prepare all iteration metrics so they are listed at the end of
499499
// of the _metrics object, before "Total" and "Score".
500500
for (let i = 0; i < this._iterationCount; i++)
501-
iterationTotalMetric(i).description = `Test totals for iteration ${i}`;
501+
iterationMetric(i, "Total").description = `Test totals for iteration ${i}`;
502502
getMetric("Geomean", "ms").description = "Geomean of test totals";
503503
getMetric("Score", "score").description = "Scaled inverse of the Geomean";
504+
if (params.measurePrepare)
505+
getMetric("Prepare", "ms").description = "Geomean of workload prepare times";
504506
}
505507

506508
const geomean = getMetric("Geomean");
507-
const iterationTotal = iterationTotalMetric(geomean.length);
509+
const iteration = geomean.length;
510+
const iterationTotal = iterationMetric(iteration, "Total");
508511
for (const results of Object.values(iterationResults))
509512
iterationTotal.add(results.total);
510513
iterationTotal.computeAggregatedMetrics();
511514
geomean.add(iterationTotal.geomean);
512515
getMetric("Score").add(geomeanToScore(iterationTotal.geomean));
513516

517+
if (params.measurePrepare) {
518+
const iterationPrepare = iterationMetric(iteration, "Prepare");
519+
for (const results of Object.values(iterationResults))
520+
iterationPrepare.add(results.prepare);
521+
iterationPrepare.computeAggregatedMetrics();
522+
const prepare = getMetric("Prepare");
523+
prepare.add(iterationPrepare.geomean);
524+
}
525+
514526
for (const metric of Object.values(this._metrics))
515527
metric.computeAggregatedMetrics();
516528
}
529+
530+
_initializeMetrics() {}
517531
}

resources/developer-mode.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export function createDeveloperModeContainer() {
1818
const settings = document.createElement("div");
1919
settings.className = "settings";
2020
settings.append(createUIForIterationCount());
21+
settings.append(createUIForMeasurePrepare());
2122
settings.append(createUIForWarmupSuite());
2223
settings.append(createUIForWarmupBeforeSync());
2324
settings.append(createUIForSyncStepDelay());
@@ -47,6 +48,12 @@ function createUIForWarmupSuite() {
4748
});
4849
}
4950

51+
function createUIForMeasurePrepare() {
52+
return createCheckboxUI("Measure Prepare", params.measurePrepare, (isChecked) => {
53+
params.measurePrepare = isChecked;
54+
});
55+
}
56+
5057
function createUIForAsyncSteps() {
5158
return createCheckboxUI("Use Async Steps", params.useAsyncSteps, (isChecked) => {
5259
params.useAsyncSteps = isChecked;

resources/main.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,11 @@ class MainBenchmarkClient {
250250
const trackHeight = 24;
251251
document.documentElement.style.setProperty("--metrics-line-height", `${trackHeight}px`);
252252
const plotWidth = (params.viewport.width - 120) / 2;
253-
document.getElementById("geomean-chart").innerHTML = renderMetricView({
254-
metrics: [metrics.Geomean],
253+
const aggregateMetrics = [metrics.Geomean];
254+
if (params.measurePrepare)
255+
aggregateMetrics.push(metrics.Prepare);
256+
document.getElementById("aggregate-chart").innerHTML = renderMetricView({
257+
metrics: aggregateMetrics,
255258
width: plotWidth,
256259
trackHeight,
257260
renderChildren: false,

resources/shared/benchmark.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class BenchmarkSuite {
4444
async runAndRecord(params, onProgress) {
4545
const measuredValues = {
4646
tests: {},
47+
prepare: 0,
4748
total: 0,
4849
};
4950
const suiteStartLabel = `suite-${this.name}-start`;

resources/shared/params.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export class Params {
3131
shuffleSeed = "off";
3232
// Choices: getBoundingClientRect or elementFromPoint
3333
layoutMode = "getBoundingClientRect";
34+
// Measure more workload prepare time.
35+
measurePrepare = false;
3436

3537
constructor(searchParams = undefined) {
3638
if (searchParams)
@@ -62,6 +64,7 @@ export class Params {
6264
this.measurementMethod = this._parseEnumParam(searchParams, "measurementMethod", ["raf"]);
6365
this.shuffleSeed = this._parseShuffleSeed(searchParams);
6466
this.layoutMode = this._parseEnumParam(searchParams, "layoutMode", LAYOUT_MODES);
67+
this.measurePrepare = this._parseBooleanParam(searchParams, "measurePrepare");
6568

6669
const unused = Array.from(searchParams.keys());
6770
if (unused.length > 0)

resources/suite-runner.mjs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ export class SuiteRunner {
88
#suite;
99
#client;
1010
#suiteResults;
11+
#prepareTime = 0;
1112

1213
constructor(frame, page, params, suite, client, measuredValues) {
1314
// FIXME: Create SuiteRunner-local measuredValues.
1415
this.#suiteResults = measuredValues.tests[suite.name];
1516
if (!this.#suiteResults) {
16-
this.#suiteResults = { tests: {}, total: 0 };
17+
this.#suiteResults = { tests: {}, prepare: 0, total: 0 };
1718
measuredValues.tests[suite.name] = this.#suiteResults;
1819
}
1920
this.#frame = frame;
@@ -62,7 +63,8 @@ export class SuiteRunner {
6263
await this.#suite.prepare(this.#page);
6364
performance.mark(suitePrepareEndLabel);
6465

65-
performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel);
66+
const entry = performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel);
67+
this.#prepareTime = entry.duration;
6668
}
6769

6870
async _runSuite() {
@@ -83,17 +85,19 @@ export class SuiteRunner {
8385
performance.mark(suiteEndLabel);
8486

8587
performance.measure(`suite-${suiteName}`, suiteStartLabel, suiteEndLabel);
86-
this._validateSuiteTotal();
88+
this._validateSuiteResults();
8789
await this._updateClient();
8890
}
8991

90-
_validateSuiteTotal() {
92+
_validateSuiteResults() {
9193
// When the test is fast and the precision is low (for example with Firefox'
9294
// privacy.resistFingerprinting preference), it's possible that the measured
9395
// total duration for an entire is 0.
94-
const suiteTotal = this.#suiteResults.total;
96+
const { suiteTotal, suitePrepare } = this.#suiteResults.total;
9597
if (suiteTotal === 0)
9698
throw new Error(`Got invalid 0-time total for suite ${this.#suite.name}: ${suiteTotal}`);
99+
if (this.#params.measurePrepare && suitePrepare === 0)
100+
throw new Error(`Got invalid 0-time prepare time for suite ${this.#suite.name}: ${suitePrepare}`);
97101
}
98102

99103
async _loadFrame() {
@@ -110,9 +114,13 @@ export class SuiteRunner {
110114
if (this.#suite === WarmupSuite)
111115
return;
112116

113-
const total = syncTime + asyncTime;
114-
this.#suiteResults.tests[test.name] = { tests: { Sync: syncTime, Async: asyncTime }, total: total };
115-
this.#suiteResults.total += total;
117+
let total = syncTime + asyncTime;
118+
this.#suiteResults.tests[test.name] = {
119+
tests: { Sync: syncTime, Async: asyncTime },
120+
total: total,
121+
};
122+
this.#suiteResults.prepare = this.#prepareTime;
123+
this.#suiteResults.total = total;
116124
};
117125

118126
async _updateClient(suite = this.#suite) {
@@ -123,6 +131,7 @@ export class SuiteRunner {
123131

124132
export class RemoteSuiteRunner extends SuiteRunner {
125133
#appId;
134+
#prepareTime;
126135

127136
get appId() {
128137
return this.#appId;
@@ -163,7 +172,8 @@ export class RemoteSuiteRunner extends SuiteRunner {
163172

164173
performance.mark(suitePrepareEndLabel);
165174

166-
performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel);
175+
const entry = performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel);
176+
this.#prepareTime = entry.duration;
167177
}
168178

169179
async _runSuite() {
@@ -177,9 +187,10 @@ export class RemoteSuiteRunner extends SuiteRunner {
177187
...response.result.tests,
178188
};
179189

180-
this.suiteResults.total += response.result.total;
190+
this.suiteResults.prepare = this.#prepareTime;
191+
this.suiteResults.total = response.result.total;
181192

182-
this._validateSuiteTotal();
193+
this._validateSuiteResults();
183194
await this._updateClient();
184195
}
185196

tests/unittests/benchmark-runner.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,15 @@ describe("BenchmarkRunner", () => {
138138
});
139139

140140
describe("runSuite", () => {
141-
let _prepareSuiteSpy, _loadFrameStub, _runTestStub, _validateSuiteTotalStub, _suitePrepareSpy, performanceMarkSpy;
141+
let _prepareSuiteSpy, _loadFrameStub, _runTestStub, _validateSuiteRessultsStub, _suitePrepareSpy, performanceMarkSpy;
142142

143143
const suite = SUITES_FIXTURE[0];
144144

145145
before(async () => {
146146
_prepareSuiteSpy = spy(SuiteRunner.prototype, "_prepareSuite");
147147
_loadFrameStub = stub(SuiteRunner.prototype, "_loadFrame").callsFake(async () => null);
148148
_runTestStub = stub(TestRunner.prototype, "runTest").callsFake(async () => null);
149-
_validateSuiteTotalStub = stub(SuiteRunner.prototype, "_validateSuiteTotal").callsFake(async () => null);
149+
_validateSuiteRessultsStub = stub(SuiteRunner.prototype, "_validateSuiteResults").callsFake(async () => null);
150150
performanceMarkSpy = spy(window.performance, "mark");
151151
_suitePrepareSpy = spy(suite, "prepare");
152152

@@ -161,7 +161,7 @@ describe("BenchmarkRunner", () => {
161161

162162
it("should run and record results for every test in suite", async () => {
163163
assert.calledThrice(_runTestStub);
164-
assert.calledOnce(_validateSuiteTotalStub);
164+
assert.calledOnce(_validateSuiteRessultsStub);
165165
assert.calledWith(performanceMarkSpy, "suite-Suite 1-prepare-start");
166166
assert.calledWith(performanceMarkSpy, "suite-Suite 1-prepare-end");
167167
assert.calledWith(performanceMarkSpy, "suite-Suite 1-start");

0 commit comments

Comments
 (0)