Skip to content

Commit 0746a31

Browse files
authored
Add measurePrepare param (#440)
Collect the suite prepare time as separate metric if param.measurePrepare is set.
1 parent bb9e3e1 commit 0746a31

File tree

8 files changed

+60
-21
lines changed

8 files changed

+60
-21
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: 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());
@@ -46,6 +47,12 @@ function createUIForWarmupSuite() {
4647
});
4748
}
4849

50+
function createUIForMeasurePrepare() {
51+
return createCheckboxUI("Measure Prepare", params.measurePrepare, (isChecked) => {
52+
params.measurePrepare = isChecked;
53+
});
54+
}
55+
4956
function createUIForAsyncSteps() {
5057
return createCheckboxUI("Use Async Steps", params.useAsyncSteps, (isChecked) => {
5158
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
@@ -27,6 +27,8 @@ export class Params {
2727
// "generate": generate a random seed
2828
// <integer>: use the provided integer as a seed
2929
shuffleSeed = "off";
30+
// Measure more workload prepare time.
31+
measurePrepare = false;
3032

3133
constructor(searchParams = undefined) {
3234
if (searchParams)
@@ -57,6 +59,7 @@ export class Params {
5759
this.warmupBeforeSync = this._parseIntParam(searchParams, "warmupBeforeSync", 0);
5860
this.measurementMethod = this._parseMeasurementMethod(searchParams);
5961
this.shuffleSeed = this._parseShuffleSeed(searchParams);
62+
this.measurePrepare = this._parseBooleanParam(searchParams, "measurePrepare");
6063

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