Skip to content

Commit

Permalink
fix(api-base): resolve resource promises in parallel
Browse files Browse the repository at this point in the history
Summary: When fetching built-in resources (e.g. techlibs) for the virtual
filesystem, do it in parallel by building up an array of promises and resolving
them via `Promise.all`, rather than doing so sequentially.

A nice effect of this is that it helps avoid HOL blocking when the resource
might be non-local e.g. your in-browser HTTP request to a CDN or server suddenly
starts having bad latency.

It also lets us get away with less logging (ref: #2), and removing these
explicit `console.log` calls actually fixes an awkward case where `printLine`
is set to a no-op function to keep things quiet, but these logs would still get
output with no way to suppress it. (If this is ever brought back it should at
least respect the `printLine` callback.)

Fixes #2.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Ie8085a216c22576d6956f007e2859e2381a56a12
  • Loading branch information
thoughtpolice committed Jan 6, 2024
1 parent 4c7fe71 commit 0434b13
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions lib/api-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export class BaseApplication {

async _fetchResources() {
// Async import, to allow inlining some of the resources within resource file.
console.log(`[YoWASP runtime] Fetching resource bundle ${this.resourceFileURL}`);
const { modules, filesystem } = await import(this.resourceFileURL);
return {
modules: await this._fetchObject(modules, this._fetchWebAssembly),
Expand All @@ -60,16 +59,21 @@ export class BaseApplication {

async _fetchObject(obj, fetchFn) {
// Mutate the object being fetched, to avoid re-fetches within the same session.
// Do this in parallel to avoid HOL blocking.
const promises = [];
for (const [key, value] of Object.entries(obj)) {
if (value instanceof URL) {
console.log(`[YoWASP runtime] Fetching resource file ${value}`);
obj[key] = await fetchFn(value);
promises.push(fetchFn(value).then((fetched) => [key, fetched]));
} else if (typeof value === "string" || value instanceof Uint8Array) {
obj[key] = value;
promises.push(Promise.resolve([key, value]));
} else {
obj[key] = await this._fetchObject(value, fetchFn);
promises.push(this._fetchObject(value, fetchFn).then((fetched) => [key, fetched]));
}
}

for (const [key, value] of await Promise.all(promises))
obj[key] = value;

return obj;
}

Expand Down

0 comments on commit 0434b13

Please sign in to comment.