Skip to content

Commit 1dbb861

Browse files
authored
Improve Benchmark constructor and instance variables (#255)
- Use plan as options bag for constructor arguments - Prefix "protected" instance variables with "_" - Rename Benchmark.preload to Benchmark._preloadEntries - Move iteration and worstCase count processing to the Benchmark class - Add files and preloadEntries getters so we can override it in GroupedBenchmark - Rename plan.arguments to plan.args due to "argument" being a reserved word - Rename WasmLegacyBenchmark to AsyncWasmLegacyBenchmark
1 parent b065e59 commit 1dbb861

File tree

2 files changed

+104
-91
lines changed

2 files changed

+104
-91
lines changed

JetStreamDriver.js

Lines changed: 102 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,6 @@ function displayCategoryScores() {
5656
document.body.classList.add("details");
5757
}
5858

59-
function getIterationCount(plan) {
60-
if (plan.name in JetStreamParams.testIterationCountMap)
61-
return JetStreamParams.testIterationCountMap[plan.name];
62-
if (JetStreamParams.testIterationCount)
63-
return JetStreamParams.testIterationCount;
64-
if (plan.iterations)
65-
return plan.iterations;
66-
return defaultIterationCount;
67-
}
68-
69-
function getWorstCaseCount(plan) {
70-
if (plan.name in JetStreamParams.testWorstCaseCountMap)
71-
return JetStreamParams.testWorstCaseCountMap[plan.name];
72-
if (JetStreamParams.testWorstCaseCount)
73-
return JetStreamParams.testWorstCaseCount;
74-
if (plan.worstCaseCount !== undefined)
75-
return plan.worstCaseCount;
76-
return defaultWorstCaseCount;
77-
}
7859

7960
if (isInBrowser) {
8061
document.onkeydown = (keyboardEvent) => {
@@ -336,7 +317,7 @@ class Driver {
336317
this.errors = [];
337318
// Make benchmark list unique and sort it.
338319
this.benchmarks = Array.from(new Set(benchmarks));
339-
this.benchmarks.sort((a, b) => a.plan.name.toLowerCase() < b.plan.name.toLowerCase() ? 1 : -1);
320+
this.benchmarks.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? 1 : -1);
340321
console.assert(this.benchmarks.length, "No benchmarks selected");
341322
}
342323

@@ -504,7 +485,7 @@ class Driver {
504485
if (isInBrowser)
505486
window.addEventListener("error", (e) => this.pushError("driver startup", e.error));
506487
await this.prefetchResources();
507-
this.benchmarks.sort((a, b) => a.plan.name.toLowerCase() < b.plan.name.toLowerCase() ? 1 : -1);
488+
this.benchmarks.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? 1 : -1);
508489
if (isInBrowser)
509490
this.prepareBrowserUI();
510491
this.isReady = true;
@@ -859,21 +840,45 @@ class BrowserScripts extends Scripts {
859840

860841

861842
class Benchmark {
862-
constructor(plan)
863-
{
864-
this.plan = plan;
865-
this.tags = this.processTags(plan.tags)
866-
this.iterations = getIterationCount(plan);
867-
this.isAsync = !!plan.isAsync;
868-
this.allowUtf16 = !!plan.allowUtf16;
869-
this.scripts = null;
870-
this.preloads = [];
871-
this.shellPrefetchedResources = null;
872-
this.results = [];
843+
constructor({
844+
name,
845+
files,
846+
preload = {},
847+
tags,
848+
iterations,
849+
deterministicRandom = false,
850+
exposeBrowserTest = false,
851+
allowUtf16 = false,
852+
args = {} }) {
873853
this._state = BenchmarkState.READY;
854+
this.results = [];
855+
856+
this.name = name
857+
this.tags = this._processTags(tags)
858+
this._arguments = args;
859+
860+
this.iterations = this._processIterationCount(iterations);
861+
this._deterministicRandom = deterministicRandom;
862+
this._exposeBrowserTest = exposeBrowserTest;
863+
this.allowUtf16 = !!allowUtf16;
864+
865+
// Resource handling:
866+
this._scripts = null;
867+
this._files = files;
868+
this._preloadEntries = Object.entries(preload);
869+
this._preloadBlobData = [];
870+
this._shellPrefetchedResources = null;
874871
}
875872

876-
processTags(rawTags) {
873+
// Use getter so it can be overridden in subclasses (GroupedBenchmark).
874+
get files() {
875+
return this._files;
876+
}
877+
get preloadEntries() {
878+
return this._preloadEntries;
879+
}
880+
881+
_processTags(rawTags) {
877882
const tags = new Set(rawTags.map(each => each.toLowerCase()));
878883
if (tags.size != rawTags.length)
879884
throw new Error(`${this.name} got duplicate tags: ${rawTags.join()}`);
@@ -883,9 +888,25 @@ class Benchmark {
883888
return tags;
884889
}
885890

886-
get name() { return this.plan.name; }
887-
get files() { return this.plan.files; }
888-
get preloadFiles() { return Object.values(this.plan.preload ?? {}); }
891+
_processIterationCount(iterations) {
892+
if (this.name in JetStreamParams.testIterationCountMap)
893+
return JetStreamParams.testIterationCountMap[this.name];
894+
if (JetStreamParams.testIterationCount)
895+
return JetStreamParams.testIterationCount;
896+
if (iterations)
897+
return iterations;
898+
return defaultIterationCount;
899+
}
900+
901+
_processWorstCaseCount(worstCaseCount) {
902+
if (this.name in JetStreamParams.testWorstCaseCountMap)
903+
return JetStreamParams.testWorstCaseCountMap[plan.name];
904+
if (JetStreamParams.testWorstCaseCount)
905+
return JetStreamParams.testWorstCaseCount;
906+
if (worstCaseCount !== undefined)
907+
return worstCaseCount;
908+
return defaultWorstCaseCount;
909+
}
889910

890911
get isDone() {
891912
return this._state == BenchmarkState.DONE || this._state == BenchmarkState.ERROR;
@@ -898,7 +919,7 @@ class Benchmark {
898919

899920
get benchmarkArguments() {
900921
return {
901-
...this.plan.arguments,
922+
...this._arguments,
902923
iterationCount: this.iterations,
903924
};
904925
}
@@ -975,7 +996,7 @@ class Benchmark {
975996

976997
get preIterationCode() {
977998
let code = this.prepareForNextIterationCode ;
978-
if (this.plan.deterministicRandom)
999+
if (this._deterministicRandom)
9791000
code += `Math.random.__resetSeed();`;
9801001

9811002
if (JetStreamParams.customPreIterationCode)
@@ -1036,24 +1057,26 @@ class Benchmark {
10361057
globalThis?.gc();
10371058
}
10381059

1039-
const scripts = isInBrowser ? new BrowserScripts(this.preloads) : new ShellScripts(this.preloads);
1060+
const scripts = isInBrowser ?
1061+
new BrowserScripts(this._preloadBlobData) :
1062+
new ShellScripts(this._preloadBlobData);
10401063

1041-
if (!!this.plan.deterministicRandom)
1064+
if (this._deterministicRandom)
10421065
scripts.addDeterministicRandom()
1043-
if (!!this.plan.exposeBrowserTest)
1066+
if (this._exposeBrowserTest)
10441067
scripts.addBrowserTest();
10451068

1046-
if (this.shellPrefetchedResources) {
1047-
scripts.addPrefetchedResources(this.shellPrefetchedResources);
1069+
if (this._shellPrefetchedResources) {
1070+
scripts.addPrefetchedResources(this._shellPrefetchedResources);
10481071
}
10491072

10501073
const prerunCode = this.prerunCode;
10511074
if (prerunCode)
10521075
scripts.add(prerunCode);
10531076

10541077
if (!isInBrowser) {
1055-
console.assert(this.scripts && this.scripts.length === this.files.length);
1056-
for (const text of this.scripts)
1078+
console.assert(this._scripts && this._scripts.length === this.files.length);
1079+
for (const text of this._scripts)
10571080
scripts.add(text);
10581081
} else {
10591082
for (const file of this.files) {
@@ -1110,30 +1133,27 @@ class Benchmark {
11101133
async prefetchResourcesForBrowser() {
11111134
console.assert(isInBrowser);
11121135
const promises = this.files.map((file) => browserFileLoader.prefetchResourceFile(file));
1113-
for (const [name, resource] of Object.entries(this.plan.preload ?? {})) {
1136+
for (const [name, resource] of this.preloadEntries) {
11141137
promises.push(this.prefetchResourcePreload(name, resource));
11151138
}
11161139
await Promise.all(promises);
11171140
}
11181141

11191142
async prefetchResourcePreload(name, resource) {
11201143
const preloadData = await browserFileLoader.prefetchResourcePreload(name, resource);
1121-
this.preloads.push(preloadData);
1144+
this._preloadBlobData.push(preloadData);
11221145
}
11231146

11241147
prefetchResourcesForShell() {
11251148
// FIXME: move to ShellFileLoader.
11261149
console.assert(!isInBrowser);
11271150

1128-
console.assert(this.scripts === null, "This initialization should be called only once.");
1129-
this.scripts = this.files.map(file => shellFileLoader.load(file));
1151+
console.assert(this._scripts === null, "This initialization should be called only once.");
1152+
this._scripts = this.files.map(file => shellFileLoader.load(file));
11301153

1131-
console.assert(this.preloads.length === 0, "This initialization should be called only once.");
1132-
this.shellPrefetchedResources = Object.create(null);
1133-
if (!this.plan.preload) {
1134-
return;
1135-
}
1136-
for (let [name, resource] of Object.entries(this.plan.preload)) {
1154+
console.assert(this._preloadBlobData.length === 0, "This initialization should be called only once.");
1155+
this._shellPrefetchedResources = Object.create(null);
1156+
for (let [name, resource] of this.preloadEntries) {
11371157
const compressed = isCompressed(resource);
11381158
if (compressed && !JetStreamParams.prefetchResources) {
11391159
resource = uncompressedName(resource);
@@ -1144,10 +1164,10 @@ class Benchmark {
11441164
if (compressed) {
11451165
bytes = zlib.decompress(bytes);
11461166
}
1147-
this.shellPrefetchedResources[resource] = bytes;
1167+
this._shellPrefetchedResources[resource] = bytes;
11481168
}
11491169

1150-
this.preloads.push({ name, resource, blobURLOrPath: resource });
1170+
this._preloadBlobData.push({ name, resource, blobURLOrPath: resource });
11511171
}
11521172
}
11531173

@@ -1267,7 +1287,8 @@ class Benchmark {
12671287
tearDown() {
12681288
if (isInBrowser) {
12691289
browserFileLoader.free(this.files);
1270-
browserFileLoader.free(this.preloadFiles);
1290+
const preloadFiles = this.preloadEntries.map(([_, file]) => file);
1291+
browserFileLoader.free(preloadFiles);
12711292
}
12721293
}
12731294
};
@@ -1315,10 +1336,11 @@ class GroupedBenchmark extends Benchmark {
13151336
}
13161337

13171338
get files() {
1318-
let files = [];
1319-
for (const benchmark of this.benchmarks)
1320-
files = files.concat(benchmark.files);
1321-
return files;
1339+
return this.benchmarks.flatMap(benchmark => benchmark.files)
1340+
}
1341+
1342+
get preloadEntries() {
1343+
return this.benchmarks.flatMap(benchmark => benchmark.preloadEntries)
13221344
}
13231345

13241346
async run() {
@@ -1398,10 +1420,10 @@ class GroupedBenchmark extends Benchmark {
13981420
};
13991421

14001422
class DefaultBenchmark extends Benchmark {
1401-
constructor(...args) {
1402-
super(...args);
1423+
constructor({worstCaseCount, ...args}) {
1424+
super(args);
14031425

1404-
this.worstCaseCount = getWorstCaseCount(this.plan);
1426+
this.worstCaseCount = this._processWorstCaseCount(worstCaseCount);
14051427
this.firstIterationTime = null;
14061428
this.firstIterationScore = null;
14071429
this.worstTime = null;
@@ -1582,8 +1604,8 @@ class WasmEMCCBenchmark extends AsyncBenchmark {
15821604
};
15831605

15841606
class WSLBenchmark extends Benchmark {
1585-
constructor(...args) {
1586-
super(...args);
1607+
constructor(plan) {
1608+
super(plan);
15871609

15881610
this.stdlibTime = null;
15891611
this.stdlibScore = null;
@@ -1645,10 +1667,9 @@ class WSLBenchmark extends Benchmark {
16451667
}
16461668
};
16471669

1648-
class WasmLegacyBenchmark extends Benchmark {
1649-
constructor(...args) {
1650-
super(...args);
1651-
1670+
class AsyncWasmLegacyBenchmark extends Benchmark {
1671+
constructor(plan) {
1672+
super(plan);
16521673
this.startupTime = null;
16531674
this.startupScore = null;
16541675
this.runTime = null;
@@ -1751,19 +1772,15 @@ class WasmLegacyBenchmark extends Benchmark {
17511772

17521773
str += "};\n";
17531774
let preloadCount = 0;
1754-
for (const [name, resource] of Object.entries(this.plan.preload)) {
1775+
for (const [name, resource] of this.preloadEntries) {
17551776
preloadCount++;
17561777
str += `JetStream.loadBlob(${JSON.stringify(name)}, "${resource}", () => {\n`;
17571778
}
1758-
if (this.plan.async) {
1759-
str += `doRun().catch((e) => {
1760-
console.log("error running wasm:", e);
1761-
console.log(e.stack)
1762-
throw e;
1763-
});`;
1764-
} else {
1765-
str += `doRun();`
1766-
}
1779+
str += `doRun().catch((e) => {
1780+
console.log("error running wasm:", e);
1781+
console.log(e.stack)
1782+
throw e;
1783+
});`;
17671784
for (let i = 0; i < preloadCount; ++i) {
17681785
str += `})`;
17691786
}
@@ -2556,7 +2573,7 @@ let BENCHMARKS = [
25562573
allowUtf16: true,
25572574
tags: ["Wasm", "transformersjs"],
25582575
}),
2559-
new WasmLegacyBenchmark({
2576+
new AsyncWasmLegacyBenchmark({
25602577
name: "tfjs-wasm",
25612578
files: [
25622579
"./wasm/tfjs-model-helpers.js",
@@ -2572,13 +2589,12 @@ let BENCHMARKS = [
25722589
preload: {
25732590
tfjsBackendWasmBlob: "./wasm/tfjs-backend-wasm.wasm",
25742591
},
2575-
async: true,
25762592
deterministicRandom: true,
25772593
exposeBrowserTest: true,
25782594
allowUtf16: true,
25792595
tags: ["Wasm"],
25802596
}),
2581-
new WasmLegacyBenchmark({
2597+
new AsyncWasmLegacyBenchmark({
25822598
name: "tfjs-wasm-simd",
25832599
files: [
25842600
"./wasm/tfjs-model-helpers.js",
@@ -2594,7 +2610,6 @@ let BENCHMARKS = [
25942610
preload: {
25952611
tfjsBackendWasmSimdBlob: "./wasm/tfjs-backend-wasm-simd.wasm",
25962612
},
2597-
async: true,
25982613
deterministicRandom: true,
25992614
exposeBrowserTest: true,
26002615
allowUtf16: true,
@@ -2624,7 +2639,7 @@ let BENCHMARKS = [
26242639
preload: {
26252640
BUNDLE: "./babylonjs/dist/bundle.es5.min.js",
26262641
},
2627-
arguments: {
2642+
args: {
26282643
expectedCacheCommentCount: 23988,
26292644
},
26302645
tags: ["startup", "js", "class", "es5", "babylonjs"],
@@ -2639,7 +2654,7 @@ let BENCHMARKS = [
26392654
preload: {
26402655
BUNDLE: "./babylonjs/dist/bundle.es6.min.js",
26412656
},
2642-
arguments: {
2657+
args: {
26432658
expectedCacheCommentCount: 21222,
26442659
},
26452660
tags: ["Default", "js", "startup", "class", "es6", "babylonjs"],

tests/unit-tests.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,8 @@ function assertThrows(message, func) {
186186
checkFile(benchmark.name, file, "file");
187187
}
188188

189-
if (benchmark.plan.preload) {
190-
for (const [name, file] of Object.entries(benchmark.plan.preload)) {
191-
checkFile(benchmark.name, file, `preload.${name}`);
192-
}
189+
for (const [name, file] of benchmark.preloadEntries) {
190+
checkFile(benchmark.name, file, `preload.${name}`);
193191
}
194192
}
195193
})();

0 commit comments

Comments
 (0)