Skip to content

Commit 18ab3a1

Browse files
committed
fixes
1 parent 515ab50 commit 18ab3a1

1 file changed

Lines changed: 150 additions & 135 deletions

File tree

JetStreamDriver.js

Lines changed: 150 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,137 @@ class ShellFileLoader {
202202
}
203203
};
204204

205+
206+
class BrowserFileLoader {
207+
208+
constructor() {
209+
// TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
210+
// the global `fileLoader` cache.
211+
this.blobDataCache = { __proto__ : null };
212+
this.loadCache = { __proto__ : null };
213+
}
214+
215+
async doLoadBlob(resource) {
216+
const blobData = this.blobDataCache[resource];
217+
218+
const compressed = isCompressed(resource);
219+
if (compressed && !JetStreamParams.prefetchResources) {
220+
resource = uncompressedName(resource);
221+
}
222+
223+
// If we aren't supposed to prefetch this then set the blobURL to just
224+
// be the resource URL.
225+
if (!JetStreamParams.prefetchResources) {
226+
blobData.blobURL = resource;
227+
return blobData;
228+
}
229+
230+
let response;
231+
let tries = 3;
232+
while (tries--) {
233+
let hasError = false;
234+
try {
235+
response = await fetch(resource, { cache: "no-store" });
236+
} catch (e) {
237+
hasError = true;
238+
}
239+
if (!hasError && response.ok)
240+
break;
241+
if (tries)
242+
continue;
243+
throw new Error("Fetch failed");
244+
}
245+
246+
// If we need to decompress this, then run it through a decompression
247+
// stream.
248+
if (compressed) {
249+
const stream = response.body.pipeThrough(new DecompressionStream("deflate"))
250+
response = new Response(stream);
251+
}
252+
253+
let blob = await response.blob();
254+
blobData.blob = blob;
255+
blobData.blobURL = URL.createObjectURL(blob);
256+
return blobData;
257+
}
258+
259+
async loadBlob(type, prop, resource, incrementRefCount = true) {
260+
let blobData = this.blobDataCache[resource];
261+
if (!blobData) {
262+
blobData = {
263+
type: type,
264+
prop: prop,
265+
resource: resource,
266+
blob: null,
267+
blobURL: null,
268+
refCount: 0
269+
};
270+
this.blobDataCache[resource] = blobData;
271+
}
272+
273+
if (incrementRefCount)
274+
blobData.refCount++;
275+
276+
let promise = this.loadCache[resource];
277+
if (promise)
278+
return promise;
279+
280+
promise = this.doLoadBlob(resource);
281+
this.loadCache[resource] = promise;
282+
return promise;
283+
}
284+
285+
async retryPrefetchResource(type, prop, file) {
286+
console.assert(isInBrowser);
287+
288+
const counter = JetStream.counter;
289+
const blobData = this.blobDataCache[file];
290+
if (blobData.blob) {
291+
// The same preload blob may be used by multiple subtests. Though the blob is already loaded,
292+
// we still need to check if this subtest failed to load it before. If so, handle accordingly.
293+
if (type == "preload") {
294+
if (this.failedPreloads && this.failedPreloads[blobData.prop]) {
295+
this.failedPreloads[blobData.prop] = false;
296+
this.preloads.push({ name: blobData.prop, resource: blobData.resource, blobURLOrPath: blobData.blobURL });
297+
counter.failedPreloadResources--;
298+
}
299+
}
300+
return !counter.failedPreloadResources && counter.loadedResources == counter.totalResources;
301+
}
302+
303+
// Retry fetching the resource.
304+
this.loadCache[file] = null;
305+
await this.loadBlob(type, prop, file, false).then((blobData) => {
306+
if (!globalThis.allIsGood)
307+
return;
308+
if (blobData.type == "preload")
309+
this.preloads.push({ name: blobData.prop, resource: blobData.resource, blobURLOrPath: blobData.blobURL });
310+
this.updateCounter();
311+
});
312+
313+
if (!blobData.blob) {
314+
globalThis.allIsGood = false;
315+
throw new Error("Fetch failed");
316+
}
317+
318+
return !counter.failedPreloadResources && counter.loadedResources == counter.totalResources;
319+
}
320+
321+
free(files) {
322+
for (const file of files) {
323+
const blobData = this.blobDataCache[file];
324+
// If we didn't prefetch this resource, then no need to free it
325+
if (!blobData.blob) {
326+
continue
327+
}
328+
blobData.refCount--;
329+
if (!blobData.refCount)
330+
this.blobDataCache[file] = undefined;
331+
}
332+
}
333+
}
334+
335+
const browserFileLoader = new BrowserFileLoader();
205336
const shellFileLoader = new ShellFileLoader();
206337

207338
class Driver {
@@ -213,10 +344,6 @@ class Driver {
213344
this.benchmarks = Array.from(new Set(benchmarks));
214345
this.benchmarks.sort((a, b) => a.plan.name.toLowerCase() < b.plan.name.toLowerCase() ? 1 : -1);
215346
console.assert(this.benchmarks.length, "No benchmarks selected");
216-
// TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
217-
// the global `fileLoader` cache.
218-
this.blobDataCache = { };
219-
this.loadCache = { };
220347
this.counter = { };
221348
this.counter.loadedResources = 0;
222349
this.counter.totalResources = 0;
@@ -249,17 +376,7 @@ class Driver {
249376
benchmark.updateUIAfterRun();
250377

251378
if (isInBrowser) {
252-
const cache = JetStream.blobDataCache;
253-
for (const file of benchmark.files) {
254-
const blobData = cache[file];
255-
// If we didn't prefetch this resource, then no need to free it
256-
if (!blobData.blob) {
257-
continue
258-
}
259-
blobData.refCount--;
260-
if (!blobData.refCount)
261-
cache[file] = undefined;
262-
}
379+
browserFileLoader.free(benchmark.files);
263380
}
264381
}
265382
performance.measure("runner update-ui", "update-ui-start");
@@ -423,12 +540,12 @@ class Driver {
423540

424541
// TODO: Cleanup the browser path of the preloading below and in
425542
// `prefetchResourcesForBrowser` / `retryPrefetchResourcesForBrowser`.
543+
const counter = JetStream.counter;
426544
const promises = [];
427545
for (const benchmark of this.benchmarks)
428-
promises.push(benchmark.prefetchResourcesForBrowser());
546+
promises.push(benchmark.prefetchResourcesForBrowser(counter));
429547
await Promise.all(promises);
430548

431-
const counter = JetStream.counter;
432549
if (counter.failedPreloadResources || counter.loadedResources != counter.totalResources) {
433550
for (const benchmark of this.benchmarks) {
434551
const allFilesLoaded = await benchmark.retryPrefetchResourcesForBrowser(counter);
@@ -744,6 +861,7 @@ class BrowserScripts extends Scripts {
744861
}
745862
}
746863

864+
747865
class Benchmark {
748866
constructor(plan)
749867
{
@@ -933,7 +1051,7 @@ class Benchmark {
9331051
for (const text of this.scripts)
9341052
scripts.add(text);
9351053
} else {
936-
const cache = JetStream.blobDataCache;
1054+
const cache = browserFileLoader.blobDataCache;
9371055
for (const file of this.plan.files) {
9381056
scripts.addWithURL(cache[file].blobURL);
9391057
}
@@ -984,75 +1102,6 @@ class Benchmark {
9841102
Realm.dispose(magicFrame);
9851103
}
9861104

987-
async doLoadBlob(resource) {
988-
const blobData = JetStream.blobDataCache[resource];
989-
990-
const compressed = isCompressed(resource);
991-
if (compressed && !JetStreamParams.prefetchResources) {
992-
resource = uncompressedName(resource);
993-
}
994-
995-
// If we aren't supposed to prefetch this then set the blobURL to just
996-
// be the resource URL.
997-
if (!JetStreamParams.prefetchResources) {
998-
blobData.blobURL = resource;
999-
return blobData;
1000-
}
1001-
1002-
let response;
1003-
let tries = 3;
1004-
while (tries--) {
1005-
let hasError = false;
1006-
try {
1007-
response = await fetch(resource, { cache: "no-store" });
1008-
} catch (e) {
1009-
hasError = true;
1010-
}
1011-
if (!hasError && response.ok)
1012-
break;
1013-
if (tries)
1014-
continue;
1015-
throw new Error("Fetch failed");
1016-
}
1017-
1018-
// If we need to decompress this, then run it through a decompression
1019-
// stream.
1020-
if (compressed) {
1021-
const stream = response.body.pipeThrough(new DecompressionStream("deflate"))
1022-
response = new Response(stream);
1023-
}
1024-
1025-
let blob = await response.blob();
1026-
blobData.blob = blob;
1027-
blobData.blobURL = URL.createObjectURL(blob);
1028-
return blobData;
1029-
}
1030-
1031-
async loadBlob(type, prop, resource, incrementRefCount = true) {
1032-
let blobData = JetStream.blobDataCache[resource];
1033-
if (!blobData) {
1034-
blobData = {
1035-
type: type,
1036-
prop: prop,
1037-
resource: resource,
1038-
blob: null,
1039-
blobURL: null,
1040-
refCount: 0
1041-
};
1042-
JetStream.blobDataCache[resource] = blobData;
1043-
}
1044-
1045-
if (incrementRefCount)
1046-
blobData.refCount++;
1047-
1048-
let promise = JetStream.loadCache[resource];
1049-
if (promise)
1050-
return promise;
1051-
1052-
promise = this.doLoadBlob(resource);
1053-
JetStream.loadCache[resource] = promise;
1054-
return promise;
1055-
}
10561105

10571106
updateCounter() {
10581107
const counter = JetStream.counter;
@@ -1061,10 +1110,10 @@ class Benchmark {
10611110
statusElement.innerHTML = `Loading ${counter.loadedResources} of ${counter.totalResources} ...`;
10621111
}
10631112

1064-
prefetchResourcesForBrowser() {
1113+
prefetchResourcesForBrowser(counter) {
10651114
console.assert(isInBrowser);
10661115

1067-
const promises = this.plan.files.map((file) => this.loadBlob("file", null, file).then((blobData) => {
1116+
const promises = this.plan.files.map((file) => browserFileLoader.loadBlob("file", null, file).then((blobData) => {
10681117
if (!globalThis.allIsGood)
10691118
return;
10701119
this.updateCounter();
@@ -1074,7 +1123,7 @@ class Benchmark {
10741123

10751124
if (this.plan.preload) {
10761125
for (const [name, resource] of Object.entries(this.plan.preload)) {
1077-
promises.push(this.loadBlob("preload", name, resource).then((blobData) => {
1126+
promises.push(browserFileLoader.loadBlob("preload", name, resource).then((blobData) => {
10781127
if (!globalThis.allIsGood)
10791128
return;
10801129
this.preloads.push({ name: blobData.prop, resource: blobData.resource, blobURLOrPath: blobData.blobURL });
@@ -1084,7 +1133,7 @@ class Benchmark {
10841133
if (!this.failedPreloads)
10851134
this.failedPreloads = { };
10861135
this.failedPreloads[name] = true;
1087-
JetStream.counter.failedPreloadResources++;
1136+
counter.failedPreloadResources++;
10881137
}));
10891138
}
10901139
}
@@ -1093,55 +1142,20 @@ class Benchmark {
10931142
return Promise.all(promises);
10941143
}
10951144

1096-
async retryPrefetchResource(type, prop, file) {
1097-
console.assert(isInBrowser);
1098-
1099-
const counter = JetStream.counter;
1100-
const blobData = JetStream.blobDataCache[file];
1101-
if (blobData.blob) {
1102-
// The same preload blob may be used by multiple subtests. Though the blob is already loaded,
1103-
// we still need to check if this subtest failed to load it before. If so, handle accordingly.
1104-
if (type == "preload") {
1105-
if (this.failedPreloads && this.failedPreloads[blobData.prop]) {
1106-
this.failedPreloads[blobData.prop] = false;
1107-
this.preloads.push({ name: blobData.prop, resource: blobData.resource, blobURLOrPath: blobData.blobURL });
1108-
counter.failedPreloadResources--;
1109-
}
1110-
}
1111-
return !counter.failedPreloadResources && counter.loadedResources == counter.totalResources;
1112-
}
1113-
1114-
// Retry fetching the resource.
1115-
JetStream.loadCache[file] = null;
1116-
await this.loadBlob(type, prop, file, false).then((blobData) => {
1117-
if (!globalThis.allIsGood)
1118-
return;
1119-
if (blobData.type == "preload")
1120-
this.preloads.push({ name: blobData.prop, resource: blobData.resource, blobURLOrPath: blobData.blobURL });
1121-
this.updateCounter();
1122-
});
1123-
1124-
if (!blobData.blob) {
1125-
globalThis.allIsGood = false;
1126-
throw new Error("Fetch failed");
1127-
}
1128-
1129-
return !counter.failedPreloadResources && counter.loadedResources == counter.totalResources;
1130-
}
1131-
1132-
async retryPrefetchResourcesForBrowser() {
1145+
async retryPrefetchResourcesForBrowser(counter) {
1146+
// FIXME: Move to BrowserFileLoader.
11331147
console.assert(isInBrowser);
11341148

1135-
const counter = JetStream.counter;
11361149
for (const resource of this.plan.files) {
1137-
const allDone = await this.retryPrefetchResource("file", null, resource);
1150+
const allDone = await browserFileLoader.retryPrefetchResource("file", null, resource);
1151+
11381152
if (allDone)
11391153
return true; // All resources loaded, nothing more to do.
11401154
}
11411155

11421156
if (this.plan.preload) {
11431157
for (const [name, resource] of Object.entries(this.plan.preload)) {
1144-
const allDone = await this.retryPrefetchResource("preload", name, resource);
1158+
const allDone = await browserFileLoader.retryPrefetchResource("preload", name, resource);
11451159
if (allDone)
11461160
return true; // All resources loaded, nothing more to do.
11471161
}
@@ -1150,6 +1164,7 @@ class Benchmark {
11501164
}
11511165

11521166
prefetchResourcesForShell() {
1167+
// FIXME: move to ShellFileLoader.
11531168
console.assert(!isInBrowser);
11541169

11551170
console.assert(this.scripts === null, "This initialization should be called only once.");
@@ -1303,14 +1318,14 @@ class GroupedBenchmark extends Benchmark {
13031318
this.benchmarks = benchmarks;
13041319
}
13051320

1306-
async prefetchResourcesForBrowser() {
1321+
async prefetchResourcesForBrowser(counter) {
13071322
for (const benchmark of this.benchmarks)
1308-
await benchmark.prefetchResourcesForBrowser();
1323+
await benchmark.prefetchResourcesForBrowser(counter);
13091324
}
13101325

1311-
async retryPrefetchResourcesForBrowser() {
1326+
async retryPrefetchResourcesForBrowser(counter) {
13121327
for (const benchmark of this.benchmarks)
1313-
await benchmark.retryPrefetchResourcesForBrowser();
1328+
await benchmark.retryPrefetchResourcesForBrowser(counter);
13141329
}
13151330

13161331
prefetchResourcesForShell() {

0 commit comments

Comments
 (0)