Skip to content

Commit afe4e4b

Browse files
Merge branch 'main' into core/config
2 parents 501741a + 25eb32e commit afe4e4b

File tree

9 files changed

+81
-23
lines changed

9 files changed

+81
-23
lines changed

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
@@ -468,10 +468,10 @@ export class BenchmarkRunner {
468468

469469
_appendIterationMetrics() {
470470
const getMetric = (name, unit = "ms") => this._metrics[name] || (this._metrics[name] = new Metric(name, unit));
471-
const iterationTotalMetric = (i) => {
471+
const iterationMetric = (i, name) => {
472472
if (i >= params.iterationCount)
473473
throw new Error(`Requested iteration=${i} does not exist.`);
474-
return getMetric(`Iteration-${i}-Total`);
474+
return getMetric(`Iteration-${i}-${name}`);
475475
};
476476

477477
const collectSubMetrics = (prefix, items, parent) => {
@@ -496,20 +496,34 @@ export class BenchmarkRunner {
496496
// Prepare all iteration metrics so they are listed at the end of
497497
// of the _metrics object, before "Total" and "Score".
498498
for (let i = 0; i < this._iterationCount; i++)
499-
iterationTotalMetric(i).description = `Test totals for iteration ${i}`;
499+
iterationMetric(i, "Total").description = `Test totals for iteration ${i}`;
500500
getMetric("Geomean", "ms").description = "Geomean of test totals";
501501
getMetric("Score", "score").description = "Scaled inverse of the Geomean";
502+
if (params.measurePrepare)
503+
getMetric("Prepare", "ms").description = "Geomean of workload prepare times";
502504
}
503505

504506
const geomean = getMetric("Geomean");
505-
const iterationTotal = iterationTotalMetric(geomean.length);
507+
const iteration = geomean.length;
508+
const iterationTotal = iterationMetric(iteration, "Total");
506509
for (const results of Object.values(iterationResults))
507510
iterationTotal.add(results.total);
508511
iterationTotal.computeAggregatedMetrics();
509512
geomean.add(iterationTotal.geomean);
510513
getMetric("Score").add(geomeanToScore(iterationTotal.geomean));
511514

515+
if (params.measurePrepare) {
516+
const iterationPrepare = iterationMetric(iteration, "Prepare");
517+
for (const results of Object.values(iterationResults))
518+
iterationPrepare.add(results.prepare);
519+
iterationPrepare.computeAggregatedMetrics();
520+
const prepare = getMetric("Prepare");
521+
prepare.add(iterationPrepare.geomean);
522+
}
523+
512524
for (const metric of Object.values(this._metrics))
513525
metric.computeAggregatedMetrics();
514526
}
527+
528+
_initializeMetrics() {}
515529
}

resources/developer-mode.mjs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export function createDeveloperModeContainer(_suites, _tags) {
2121
const settings = document.createElement("div");
2222
settings.className = "settings";
2323
settings.append(createUIForIterationCount());
24+
settings.append(createUIForMeasurePrepare());
2425
settings.append(createUIForWarmupSuite());
2526
settings.append(createUIForWarmupBeforeSync());
2627
settings.append(createUIForSyncStepDelay());
@@ -49,6 +50,12 @@ function createUIForWarmupSuite() {
4950
});
5051
}
5152

53+
function createUIForMeasurePrepare() {
54+
return createCheckboxUI("Measure Prepare", params.measurePrepare, (isChecked) => {
55+
params.measurePrepare = isChecked;
56+
});
57+
}
58+
5259
function createUIForAsyncSteps() {
5360
return createCheckboxUI("Use Async Steps", params.useAsyncSteps, (isChecked) => {
5461
params.useAsyncSteps = isChecked;
@@ -222,12 +229,13 @@ function createSuitesTagsButton(setSuiteEnabled) {
222229

223230
function createUIForRun() {
224231
const stepTestButton = document.createElement("button");
225-
stepTestButton.textContent = "Step Test \u23EF";
232+
stepTestButton.className = "step-button";
233+
stepTestButton.innerHTML = "Step Test<span>\u23EF</span>";
226234
stepTestButton.onclick = (event) => {
227235
globalThis.benchmarkClient.step();
228236
};
229237
const startTestButton = document.createElement("button");
230-
startTestButton.textContent = "Start Test \u23F5";
238+
startTestButton.innerHTML = "Start Test<span>\u23F5</span>";
231239
startTestButton.onclick = (event) => {
232240
globalThis.benchmarkClient.start();
233241
};

resources/main.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,28 @@ button,
287287
}
288288

289289
.developer-mode-content button {
290+
font-size: 16px;
290291
background: white;
291292
flex: auto;
292293
padding: 4px;
293294
appearance: button;
294295
border: 2px solid rgba(255, 255, 255, 0.5);
295296
border-radius: 10px;
296297
}
298+
299+
.developer-mode-content button span {
300+
padding-left: 10px;
301+
font-size: 1.5em;
302+
line-height: 10px;
303+
position: relative;
304+
top: 2px;
305+
}
306+
297307
.developer-mode-content .tag {
298308
border-radius: 100vh;
309+
}
310+
311+
.developer-mode-content .step-button {
299312
color: white;
300313
background: rgba(255, 255, 255, 0.1);
301314
}
@@ -518,6 +531,8 @@ section#details .non-standard-params {
518531
display: none;
519532
text-align: center;
520533
margin-bottom: 2em;
534+
/* Increase contrast a bit */
535+
filter: brightness(1.5);
521536
}
522537

523538
section#details .non-standard-params h2 {
@@ -547,6 +562,9 @@ section#details .non-standard-params h2 {
547562
#non-standard-params-table tbody td {
548563
padding: 0.1em 0.3em;
549564
}
565+
#non-standard-params-table tbody td:nth-child(2) {
566+
color: var(--highlight);
567+
}
550568

551569
section#details .all-metric-results {
552570
flex: auto;

resources/main.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,11 @@ class MainBenchmarkClient {
253253
const trackHeight = 24;
254254
document.documentElement.style.setProperty("--metrics-line-height", `${trackHeight}px`);
255255
const plotWidth = (params.viewport.width - 120) / 2;
256-
document.getElementById("geomean-chart").innerHTML = renderMetricView({
257-
metrics: [metrics.Geomean],
256+
const aggregateMetrics = [metrics.Geomean];
257+
if (params.measurePrepare)
258+
aggregateMetrics.push(metrics.Prepare);
259+
document.getElementById("aggregate-chart").innerHTML = renderMetricView({
260+
metrics: aggregateMetrics,
258261
width: plotWidth,
259262
trackHeight,
260263
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
@@ -29,6 +29,8 @@ export class Params {
2929
shuffleSeed = "off";
3030
// External config url to override internal tests.
3131
config = "";
32+
// Measure more workload prepare time.
33+
measurePrepare = false;
3234

3335
constructor(searchParams = undefined) {
3436
if (searchParams)
@@ -60,6 +62,7 @@ export class Params {
6062
this.measurementMethod = this._parseMeasurementMethod(searchParams);
6163
this.shuffleSeed = this._parseShuffleSeed(searchParams);
6264
this.config = this._parseConfig(searchParams);
65+
this.measurePrepare = this._parseBooleanParam(searchParams, "measurePrepare");
6366

6467
const unused = Array.from(searchParams.keys());
6568
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)