From 35fff7e3cd0173efc00d0b3ca1e0a069e8884978 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 13 Aug 2025 16:21:17 +0200 Subject: [PATCH 01/11] change --- 8bitbench/benchmark.js | 4 +- ARES-6/Babylon/benchmark.js | 10 +- Dart/benchmark.js | 4 +- JetStreamDriver.js | 169 ++++++++++++++++++--------------- Kotlin-compose/benchmark.js | 18 ++-- RexBench/UniPoker/benchmark.js | 2 +- code-load/code-first-load.js | 2 +- sqlite3/benchmark.js | 2 +- wasm/HashSet/benchmark.js | 2 +- wasm/TSF/benchmark.js | 2 +- wasm/argon2/benchmark.js | 2 +- wasm/dotnet/benchmark.js | 78 +++++++-------- wasm/gcc-loops/benchmark.js | 2 +- wasm/quicksort/benchmark.js | 2 +- wasm/richards/benchmark.js | 2 +- wasm/tfjs-bundle.js | 8 +- wasm/zlib/benchmark.js | 2 +- 17 files changed, 162 insertions(+), 149 deletions(-) diff --git a/8bitbench/benchmark.js b/8bitbench/benchmark.js index 5b6551b1..001efda9 100644 --- a/8bitbench/benchmark.js +++ b/8bitbench/benchmark.js @@ -38,8 +38,8 @@ class Benchmark { romBinary; async init() { - Module.wasmBinary = await getBinary(wasmBinary); - this.romBinary = await getBinary(romBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); + this.romBinary = await JetStream.getBinary(JetStream..preload.romBinary); } async runIteration() { diff --git a/ARES-6/Babylon/benchmark.js b/ARES-6/Babylon/benchmark.js index 8de7163e..fd4151a7 100644 --- a/ARES-6/Babylon/benchmark.js +++ b/ARES-6/Babylon/benchmark.js @@ -30,14 +30,14 @@ class Benchmark { let sources = []; const files = [ - [airBlob, {}] - , [basicBlob, {}] - , [inspectorBlob, {}] - , [babylonBlob, {sourceType: "module"}] + [JetStream.preload.airBlob, {}], + [JetStream.preload.basicBlob, {}], + [JetStream.preload.inspectorBlob, {}], + [JetStream.preload.babylonBlob, {sourceType: "module"}], ]; for (let [file, options] of files) - sources.push([file, await getString(file), options]); + sources.push([file, await JetStream.getString(file), options]); this.sources = sources; } diff --git a/Dart/benchmark.js b/Dart/benchmark.js index ae7154c0..37ebdcd3 100644 --- a/Dart/benchmark.js +++ b/Dart/benchmark.js @@ -262,8 +262,8 @@ class Benchmark { // The generated JavaScript code from dart2wasm is an ES module, which we // can only load with a dynamic import (since this file is not a module.) - Module.wasmBinary = await getBinary(wasmBinary); - this.dart2wasmJsModule = await dynamicImport(jsModule); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); + this.dart2wasmJsModule = await JetStream.dynamicImport(JetStream.preload.jsModule); } async runIteration() { diff --git a/JetStreamDriver.js b/JetStreamDriver.js index d1ef7964..faa52e29 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -561,8 +561,11 @@ class Scripts { constructor() { this.scripts = []; this.add(` - const isInBrowser = ${isInBrowser}; - const isD8 = ${isD8}; + globalThis.JetStream = { + isInBrowser: ${isInBrowser}, + isD8: ${isD8}, + preload: {}, + }; if (typeof performance.mark === 'undefined') { performance.mark = function(name) { return { name }}; } @@ -642,8 +645,14 @@ class ShellScripts extends Scripts { }; globalObject.performance ??= performance; - for (const script of this.scripts) + for (const script of this.scripts) { + try { globalObject.loadString(script); + } catch(e) { + console.log(script); + throw e; + } + } return isD8 ? realm : globalObject; } @@ -725,10 +734,10 @@ class Benchmark { } get runnerCode() { - return ` - let __benchmark = new Benchmark(${this.iterations}); - let results = []; - let benchmarkName = "${this.name}"; + return `{ + const benchmark = new Benchmark(${this.iterations}); + const results = []; + const benchmarkName = "${this.name}"; for (let i = 0; i < ${this.iterations}; i++) { ${this.preIterationCode} @@ -737,7 +746,7 @@ class Benchmark { const iterationStartMark = performance.mark(iterationMarkLabel); let start = performance.now(); - __benchmark.runIteration(); + benchmark.runIteration(i); let end = performance.now(); performance.measure(iterationMarkLabel, iterationMarkLabel); @@ -746,8 +755,9 @@ class Benchmark { results.push(Math.max(1, end - start)); } - __benchmark.validate?.(${this.iterations}); - top.currentResolve(results);`; + benchmark.validate?.(${this.iterations}); + top.currentResolve(results); + };`; } processResults(results) { @@ -773,7 +783,7 @@ class Benchmark { get prerunCode() { return null; } get preIterationCode() { - let code = `__benchmark.prepareForNextIteration?.();`; + let code = `benchmark.prepareForNextIteration?.();`; if (this.plan.deterministicRandom) code += `Math.random.__resetSeed();`; @@ -804,7 +814,7 @@ class Benchmark { if (this.plan.preload) { let preloadCode = ""; for (let [ variableName, blobURLOrPath ] of this.preloads) - preloadCode += `const ${variableName} = "${blobURLOrPath}";\n`; + preloadCode += `JetStream.preload.${variableName} = "${blobURLOrPath}";\n`; scripts.add(preloadCode); } @@ -1177,31 +1187,31 @@ class AsyncBenchmark extends DefaultBenchmark { // with this class and make all benchmarks async. if (isInBrowser) { str += ` - async function getBinary(blobURL) { + JetStream.getBinary = async function(blobURL) { const response = await fetch(blobURL); return new Int8Array(await response.arrayBuffer()); } - async function getString(blobURL) { + JetStream.getString = async function(blobURL) { const response = await fetch(blobURL); return response.text(); } - async function dynamicImport(blobURL) { + JetStream.dynamicImport = async function(blobURL) { return await import(blobURL); } `; } else { str += ` - async function getBinary(path) { + JetStream.getBinary = async function(path) { return new Int8Array(read(path, "binary")); } - async function getString(path) { + JetStream.getString = async function(path) { return read(path); } - async function dynamicImport(path) { + JetStream.dynamicImport = async function(path) { try { return await import(path); } catch (e) { @@ -1218,10 +1228,10 @@ class AsyncBenchmark extends DefaultBenchmark { get runnerCode() { return ` async function doRun() { - let __benchmark = new Benchmark(); - await __benchmark.init?.(); - let results = []; - let benchmarkName = "${this.name}"; + const benchmark = new Benchmark(${this.iterations}); + await benchmark.init?.(); + const results = []; + const benchmarkName = "${this.name}"; for (let i = 0; i < ${this.iterations}; i++) { ${this.preIterationCode} @@ -1230,7 +1240,7 @@ class AsyncBenchmark extends DefaultBenchmark { const iterationStartMark = performance.mark(iterationMarkLabel); let start = performance.now(); - await __benchmark.runIteration(); + await benchmark.runIteration(i); let end = performance.now(); performance.measure(iterationMarkLabel, iterationMarkLabel); @@ -1239,9 +1249,9 @@ class AsyncBenchmark extends DefaultBenchmark { results.push(Math.max(1, end - start)); } - __benchmark.validate?.(${this.iterations}); + benchmark.validate?.(${this.iterations}); top.currentResolve(results); - } + }; doRun().catch((error) => { top.currentReject(error); });` } }; @@ -1252,7 +1262,6 @@ class WasmEMCCBenchmark extends AsyncBenchmark { get prerunCode() { let str = ` let verbose = false; - let globalObject = this; abort = quit = function() { @@ -1260,21 +1269,23 @@ class WasmEMCCBenchmark extends AsyncBenchmark { console.log('Intercepted quit/abort'); }; - oldPrint = globalObject.print; - globalObject.print = globalObject.printErr = (...args) => { - if (verbose) - console.log('Intercepted print: ', ...args); - }; + { + const oldPrint = globalObject.print; + globalObject.print = globalObject.printErr = (...args) => { + if (verbose) + console.log('Intercepted print: ', ...args); + }; - let Module = { - preRun: [], - postRun: [], - noInitialRun: true, - print: print, - printErr: printErr - }; + let Module = { + preRun: [], + postRun: [], + noInitialRun: true, + print: print, + printErr: printErr + }; - globalObject.Module = Module; + globalObject.Module = Module; + }; ${super.prerunCode}; `; @@ -1302,34 +1313,35 @@ class WSLBenchmark extends Benchmark { get runnerCode() { return ` - let benchmark = new Benchmark(); - const benchmarkName = "${this.name}"; - - let results = []; { - const markLabel = benchmarkName + "-stdlib"; - const startMark = performance.mark(markLabel); + const benchmark = new Benchmark(); + const benchmarkName = "${this.name}"; - let start = performance.now(); - benchmark.buildStdlib(); - results.push(performance.now() - start); + let results = []; + { + const markLabel = benchmarkName + "-stdlib"; + const startMark = performance.mark(markLabel); - performance.measure(markLabel, markLabel); - } + let start = performance.now(); + benchmark.buildStdlib(); + results.push(performance.now() - start); - { - const markLabel = benchmarkName + "-mainRun"; - const startMark = performance.mark(markLabel); + performance.measure(markLabel, markLabel); + }; - let start = performance.now(); - benchmark.run(); - results.push(performance.now() - start); + { + const markLabel = benchmarkName + "-mainRun"; + const startMark = performance.mark(markLabel); - performance.measure(markLabel, markLabel); - } + let start = performance.now(); + benchmark.run(); + results.push(performance.now() - start); - top.currentResolve(results); - `; + performance.measure(markLabel, markLabel); + }; + + top.currentResolve(results); + };`; } subScores() { @@ -1387,30 +1399,31 @@ class WasmLegacyBenchmark extends Benchmark { console.log('Intercepted quit/abort'); }; - oldPrint = globalObject.print; - oldConsoleLog = globalObject.console.log; - globalObject.print = globalObject.printErr = (...args) => { - if (verbose) - oldConsoleLog('Intercepted print: ', ...args); - }; + { + const oldConsoleLog = globalObject.console.log; + globalObject.print = globalObject.printErr = (...args) => { + if (verbose) + oldConsoleLog('Intercepted print: ', ...args); + }; - let Module = { - preRun: [], - postRun: [], - print: globalObject.print, - printErr: globalObject.print + let Module = { + preRun: [], + postRun: [], + print: globalObject.print, + printErr: globalObject.print + }; + globalObject.Module = Module; }; - globalObject.Module = Module; - `; + `; return str; } get runnerCode() { - let str = `function loadBlob(key, path, andThen) {`; + let str = `JetStream.loadBlob(key, path, andThen) {`; if (isInBrowser) { str += ` - var xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); xhr.open('GET', path, true); xhr.responseType = 'arraybuffer'; xhr.onload = function() { @@ -1437,15 +1450,15 @@ class WasmLegacyBenchmark extends Benchmark { console.log(e.stack); throw e; } - }) + }); `; } - str += "}"; + str += "};\n"; const keys = Object.keys(this.plan.preload); for (let i = 0; i < keys.length; ++i) { - str += `loadBlob("${keys[i]}", "${this.plan.preload[keys[i]]}", () => {\n`; + str += `JetStream.loadBlob("${keys[i]}", "${this.plan.preload[keys[i]]}", () => {\n`; } if (this.plan.async) { str += `doRun().catch((e) => { diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 50125bb2..0aa0ffa8 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -112,20 +112,20 @@ class Benchmark { // console.log("init"); preload = { - 'skiko.wasm': await getBinary(skikoWasmBinary), - './compose-benchmarks-benchmarks.wasm': await getBinary(composeWasmBinary), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await getBinary(inputImageCompose), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await getBinary(inputImageCat), - './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await getBinary(inputImageComposeCommunity), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await getBinary(inputFontItalic), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await getBinary(inputFontRegular), + 'skiko.wasm': await JetStream.getBinary(JetStream.preload.skikoWasmBinary), + './compose-benchmarks-benchmarks.wasm': await JetStream.getBinary(JetStream.preload.composeWasmBinary), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await JetStream.getBinary(JetStream.preload.inputImageCompose), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await JetStream.getBinary(JetStream.preload.inputImageCat), + './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await JetStream.getBinary(JetStream.preload.inputImageComposeCommunity), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await JetStream.getBinary(JetStream.preload.inputFontItalic), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await JetStream.getBinary(JetStream.preload.inputFontRegular), }; // We patched `skiko.mjs` to not immediately instantiate the `skiko.wasm` // module, so that we can move the dynamic JS import here but measure // WebAssembly compilation and instantiation as part of the first iteration. - this.skikoInstantiate = (await dynamicImport(skikoJsModule)).default; - this.mainInstantiate = (await dynamicImport(composeJsModule)).instantiate; + this.skikoInstantiate = (await JetStream.dynamicImport(JetStream.skikoJsModule)).default; + this.mainInstantiate = (await JetStream.dynamicImport(JetStream.composeJsModule)).instantiate; } async runIteration() { diff --git a/RexBench/UniPoker/benchmark.js b/RexBench/UniPoker/benchmark.js index 9eebc9c9..df7ce0c5 100644 --- a/RexBench/UniPoker/benchmark.js +++ b/RexBench/UniPoker/benchmark.js @@ -46,7 +46,7 @@ class Benchmark { const playerExpectations = getPlayerExpectations(iterations) if (this._players.length != playerExpectations.length) throw "Expect " + playerExpectations.length + ", but actually have " + this._players.length; - if (isInBrowser) { + if (JetStream.isInBrowser) { for (let playerIdx = 0; playerIdx < playerExpectations.length; playerIdx++) playerExpectations[playerIdx].validate(this._players[playerIdx]); } diff --git a/code-load/code-first-load.js b/code-load/code-first-load.js index 0a9e3942..eac236aa 100644 --- a/code-load/code-first-load.js +++ b/code-load/code-first-load.js @@ -26,7 +26,7 @@ let indirectEval = eval; class Benchmark { async init() { - this.inspectorText = `let _____top_level_____ = ${Math.random()}; ${await getString(inspectorPayloadBlob)}`; + this.inspectorText = `let _____top_level_____ = ${Math.random()}; ${await JetStream.getString(JetStream.preload.inspectorPayloadBlob)}`; this.index = 0; } diff --git a/sqlite3/benchmark.js b/sqlite3/benchmark.js index 416790a5..9ee176de 100644 --- a/sqlite3/benchmark.js +++ b/sqlite3/benchmark.js @@ -53,7 +53,7 @@ class Benchmark { sqlite3Module; async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/HashSet/benchmark.js b/wasm/HashSet/benchmark.js index c5962770..bd94e57a 100644 --- a/wasm/HashSet/benchmark.js +++ b/wasm/HashSet/benchmark.js @@ -5,7 +5,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/TSF/benchmark.js b/wasm/TSF/benchmark.js index 2d369388..15f97931 100644 --- a/wasm/TSF/benchmark.js +++ b/wasm/TSF/benchmark.js @@ -25,7 +25,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/argon2/benchmark.js b/wasm/argon2/benchmark.js index 13187d3a..fff8c2fd 100644 --- a/wasm/argon2/benchmark.js +++ b/wasm/argon2/benchmark.js @@ -77,7 +77,7 @@ const saltLength = 12; class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/dotnet/benchmark.js b/wasm/dotnet/benchmark.js index 4048a30e..ba8939f9 100644 --- a/wasm/dotnet/benchmark.js +++ b/wasm/dotnet/benchmark.js @@ -6,125 +6,125 @@ class Benchmark { assets: [ { name: "dotnet.runtime.js", - resolvedUrl: dotnetRuntimeUrl, - moduleExports: await dynamicImport(dotnetRuntimeUrl), + resolvedUrl: JetStream.preload.dotnetRuntimeUrl, + moduleExports: await JetStream.dynamicImport(JetStream.preload.dotnetRuntimeUrl), behavior: "js-module-runtime" }, { name: "dotnet.native.js", - resolvedUrl: dotnetNativeUrl, - moduleExports: await dynamicImport(dotnetNativeUrl), + resolvedUrl: JetStream.preload.dotnetNativeUrl, + moduleExports: await JetStream.dynamicImport(JetStream.preload.dotnetNativeUrl), behavior: "js-module-native" }, { name: "dotnet.native.wasm", - resolvedUrl: wasmBinaryUrl, - buffer: await getBinary(wasmBinaryUrl), + resolvedUrl: JetStream.preload.wasmBinaryUrl, + buffer: await JetStream.getBinary(JetStream.preload.wasmBinaryUrl), behavior: "dotnetwasm" }, { name: "icudt_CJK.dat", - resolvedUrl: icuCustomUrl, - buffer: await getBinary(icuCustomUrl), + resolvedUrl: JetStream.preload.icuCustomUrl, + buffer: await JetStream.getBinary(JetStream.preload.icuCustomUrl), behavior: "icu" }, { name: "System.Collections.Concurrent.wasm", - resolvedUrl: dllCollectionsConcurrentUrl, - buffer: await getBinary(dllCollectionsConcurrentUrl), + resolvedUrl: JetStream.preload.dllCollectionsConcurrentUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllCollectionsConcurrentUrl), behavior: "assembly" }, { name: "System.Collections.wasm", - resolvedUrl: dllCollectionsUrl, - buffer: await getBinary(dllCollectionsUrl), + resolvedUrl: JetStream.preload.dllCollectionsUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllCollectionsUrl), behavior: "assembly" }, { name: "System.ComponentModel.Primitives.wasm", - resolvedUrl: dllComponentModelPrimitivesUrl, - buffer: await getBinary(dllComponentModelPrimitivesUrl), + resolvedUrl: JetStream.preload.dllComponentModelPrimitivesUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllComponentModelPrimitivesUrl), behavior: "assembly" }, { name: "System.ComponentModel.TypeConverter.wasm", - resolvedUrl: dllComponentModelTypeConverterUrl, - buffer: await getBinary(dllComponentModelTypeConverterUrl), + resolvedUrl: JetStream.preload.dllComponentModelTypeConverterUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllComponentModelTypeConverterUrl), behavior: "assembly" }, { name: "System.Drawing.Primitives.wasm", - resolvedUrl: dllDrawingPrimitivesUrl, - buffer: await getBinary(dllDrawingPrimitivesUrl), + resolvedUrl: JetStream.preload.dllDrawingPrimitivesUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllDrawingPrimitivesUrl), behavior: "assembly" }, { name: "System.Drawing.wasm", - resolvedUrl: dllDrawingUrl, - buffer: await getBinary(dllDrawingUrl), + resolvedUrl: JetStream.preload.dllDrawingUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllDrawingUrl), behavior: "assembly" }, { name: "System.IO.Pipelines.wasm", - resolvedUrl: dllIOPipelinesUrl, - buffer: await getBinary(dllIOPipelinesUrl), + resolvedUrl: JetStream.preload.dllIOPipelinesUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllIOPipelinesUrl), behavior: "assembly" }, { name: "System.Linq.wasm", - resolvedUrl: dllLinqUrl, - buffer: await getBinary(dllLinqUrl), + resolvedUrl: JetStream.preload.dllLinqUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllLinqUrl), behavior: "assembly" }, { name: "System.Memory.wasm", - resolvedUrl: dllMemoryUrl, - buffer: await getBinary(dllMemoryUrl), + resolvedUrl: JetStream.preload.dllMemoryUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllMemoryUrl), behavior: "assembly" }, { name: "System.ObjectModel.wasm", - resolvedUrl: dllObjectModelUrl, - buffer: await getBinary(dllObjectModelUrl), + resolvedUrl: JetStream.preload.dllObjectModelUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllObjectModelUrl), behavior: "assembly" }, { name: "System.Private.CoreLib.wasm", - resolvedUrl: dllPrivateCorelibUrl, - buffer: await getBinary(dllPrivateCorelibUrl), + resolvedUrl: JetStream.preload.dllPrivateCorelibUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllPrivateCorelibUrl), behavior: "assembly", isCore: true }, { name: "System.Runtime.InteropServices.JavaScript.wasm", - resolvedUrl: dllRuntimeInteropServicesJavaScriptUrl, - buffer: await getBinary(dllRuntimeInteropServicesJavaScriptUrl), + resolvedUrl: JetStream.preload.dllRuntimeInteropServicesJavaScriptUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllRuntimeInteropServicesJavaScriptUrl), behavior: "assembly", isCore: true }, { name: "System.Text.Encodings.Web.wasm", - resolvedUrl: dllTextEncodingsWebUrl, - buffer: await getBinary(dllTextEncodingsWebUrl), + resolvedUrl: JetStream.preload.dllTextEncodingsWebUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllTextEncodingsWebUrl), behavior: "assembly" }, { name: "System.Text.Json.wasm", - resolvedUrl: dllTextJsonUrl, - buffer: await getBinary(dllTextJsonUrl), + resolvedUrl: JetStream.preload.dllTextJsonUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllTextJsonUrl), behavior: "assembly" }, { name: "dotnet.wasm", - resolvedUrl: dllAppUrl, - buffer: await getBinary(dllAppUrl), + resolvedUrl: JetStream.preload.dllAppUrl, + buffer: await JetStream.getBinary(JetStream.preload.dllAppUrl), behavior: "assembly", isCore: true } ] }; - this.dotnet = (await dynamicImport(dotnetUrl)).dotnet; + this.dotnet = (await JetStream.dynamicImport(JetStream.dotnetUrl)).dotnet; this.api = await this.dotnet.withModuleConfig({ locateFile: e => e }).withConfig(config).create(); this.exports = await this.api.getAssemblyExports("dotnet.dll"); diff --git a/wasm/gcc-loops/benchmark.js b/wasm/gcc-loops/benchmark.js index c5962770..bd94e57a 100644 --- a/wasm/gcc-loops/benchmark.js +++ b/wasm/gcc-loops/benchmark.js @@ -5,7 +5,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/quicksort/benchmark.js b/wasm/quicksort/benchmark.js index a271ff85..a57229f6 100644 --- a/wasm/quicksort/benchmark.js +++ b/wasm/quicksort/benchmark.js @@ -5,7 +5,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/richards/benchmark.js b/wasm/richards/benchmark.js index 53dd1f48..3c02a05a 100644 --- a/wasm/richards/benchmark.js +++ b/wasm/richards/benchmark.js @@ -5,7 +5,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { diff --git a/wasm/tfjs-bundle.js b/wasm/tfjs-bundle.js index e3790532..f98b6ff1 100644 --- a/wasm/tfjs-bundle.js +++ b/wasm/tfjs-bundle.js @@ -23210,11 +23210,11 @@ } catch (e) { // ************************ CHANGE START ************************ let blob; - if (globalThis.tfjsBackendWasmSimdBlob || Module.tfjsBackendWasmSimdBlob) { - blob = globalThis.tfjsBackendWasmSimdBlob || Module.tfjsBackendWasmSimdBlob; + if (JetStream.preload.tfjsBackendWasmSimdBlob || Module.tfjsBackendWasmSimdBlob) { + blob = JetStream.preload.tfjsBackendWasmSimdBlob || Module.tfjsBackendWasmSimdBlob; // console.warn("shell tfjs instantiating wasm simd backend"); - } else if (globalThis.tfjsBackendWasmBlob || Module.tfjsBackendWasmBlob) { - blob = globalThis.tfjsBackendWasmBlob || Module.tfjsBackendWasmBlob; + } else if (JetStream.preload.tfjsBackendWasmBlob || Module.tfjsBackendWasmBlob) { + blob = JetStream.preload.tfjsBackendWasmBlob || Module.tfjsBackendWasmBlob; // console.warn("shell tfjs instantiating wasm backend"); } else console.warn("Fatal error: no binary file found for ./wasm/tfjs-backend-wasm-simd.wasm and ./wasm/tfjs-backend-wasm.wasm"); diff --git a/wasm/zlib/benchmark.js b/wasm/zlib/benchmark.js index 44a41081..5317d019 100644 --- a/wasm/zlib/benchmark.js +++ b/wasm/zlib/benchmark.js @@ -5,7 +5,7 @@ class Benchmark { async init() { - Module.wasmBinary = await getBinary(wasmBinary); + Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); } async runIteration() { From 5edea64bafb56fa8f312fd71045549668f3af999 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 13 Aug 2025 16:46:23 +0200 Subject: [PATCH 02/11] more fixes --- JetStreamDriver.js | 14 +++++++------- Kotlin-compose/benchmark.js | 4 ++-- RexBench/flightplan_benchmark.js | 4 ++-- RexBench/flightplan_unicode_benchmark.js | 4 ++-- RexBench/offline_assembler_benchmark.js | 4 ++-- RexBench/sunspider_benchmark.js | 4 ++-- RexBench/unipoker_benchmark.js | 4 ++-- code-load/code-multi-load.js | 2 +- wasm/tfjs-benchmark.js | 6 +++--- wasm/tfjs-bundle.js | 3 +-- worker/bomb.js | 2 +- 11 files changed, 25 insertions(+), 26 deletions(-) diff --git a/JetStreamDriver.js b/JetStreamDriver.js index faa52e29..f028d66d 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -1190,26 +1190,26 @@ class AsyncBenchmark extends DefaultBenchmark { JetStream.getBinary = async function(blobURL) { const response = await fetch(blobURL); return new Int8Array(await response.arrayBuffer()); - } + }; JetStream.getString = async function(blobURL) { const response = await fetch(blobURL); return response.text(); - } + }; JetStream.dynamicImport = async function(blobURL) { return await import(blobURL); - } + }; `; } else { str += ` JetStream.getBinary = async function(path) { return new Int8Array(read(path, "binary")); - } + }; JetStream.getString = async function(path) { return read(path); - } + }; JetStream.dynamicImport = async function(path) { try { @@ -1219,7 +1219,7 @@ class AsyncBenchmark extends DefaultBenchmark { // without the "./" prefix (e.g., JSC requires it). return await import(path.slice("./".length)) } - } + }; `; } return str; @@ -1419,7 +1419,7 @@ class WasmLegacyBenchmark extends Benchmark { } get runnerCode() { - let str = `JetStream.loadBlob(key, path, andThen) {`; + let str = `JetStream.loadBlob = function(key, path, andThen) {`; if (isInBrowser) { str += ` diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 0aa0ffa8..7ae3f14e 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -124,8 +124,8 @@ class Benchmark { // We patched `skiko.mjs` to not immediately instantiate the `skiko.wasm` // module, so that we can move the dynamic JS import here but measure // WebAssembly compilation and instantiation as part of the first iteration. - this.skikoInstantiate = (await JetStream.dynamicImport(JetStream.skikoJsModule)).default; - this.mainInstantiate = (await JetStream.dynamicImport(JetStream.composeJsModule)).instantiate; + this.skikoInstantiate = (await JetStream.dynamicImport(JetStream.preload.skikoJsModule)).default; + this.mainInstantiate = (await JetStream.dynamicImport(JetStream.preload.composeJsModule)).instantiate; } async runIteration() { diff --git a/RexBench/flightplan_benchmark.js b/RexBench/flightplan_benchmark.js index cb9e5534..ef05ab3b 100644 --- a/RexBench/flightplan_benchmark.js +++ b/RexBench/flightplan_benchmark.js @@ -42,7 +42,7 @@ reportResult(results); let runFlightPlannerBenchmark = null; -if (!isInBrowser) { +if (!JetStream.isInBrowser) { let sources = [ "benchmark.js" , "FlightPlanner/airways.js" @@ -62,7 +62,7 @@ const FlightPlannerBenchmarkRunner = { cells: {} }; -if (isInBrowser) { +if (JetStream.isInBrowser) { FlightPlannerBenchmarkRunner.cells = { firstIteration: document.getElementById("FlightPlannerFirstIteration"), averageWorstCase: document.getElementById("FlightPlannerAverageWorstCase"), diff --git a/RexBench/flightplan_unicode_benchmark.js b/RexBench/flightplan_unicode_benchmark.js index f30e38e3..838b0ad6 100644 --- a/RexBench/flightplan_unicode_benchmark.js +++ b/RexBench/flightplan_unicode_benchmark.js @@ -43,7 +43,7 @@ reportResult(results); let runFlightPlannerUnicodeBenchmark = null; -if (!isInBrowser) { +if (!JetStream.isInBrowser) { let sources = [ "benchmark.js" , "FlightPlanner/airways.js" @@ -64,7 +64,7 @@ const FlightPlannerUnicodeBenchmarkRunner = { cells: {} }; -if (isInBrowser) { +if (JetStream.isInBrowser) { FlightPlannerUnicodeBenchmarkRunner.cells = { firstIteration: document.getElementById("FlightPlannerUnicodeFirstIteration"), averageWorstCase: document.getElementById("FlightPlannerUnicodeAverageWorstCase"), diff --git a/RexBench/offline_assembler_benchmark.js b/RexBench/offline_assembler_benchmark.js index 61240531..998944f7 100644 --- a/RexBench/offline_assembler_benchmark.js +++ b/RexBench/offline_assembler_benchmark.js @@ -48,7 +48,7 @@ reportResult(results); let runOfflineAssemblerBenchmark = null; -if (!isInBrowser) { +if (!JetStream.isInBrowser) { let sources = [ "benchmark.js" , "OfflineAssembler/registers.js" @@ -74,7 +74,7 @@ const OfflineAssemblerBenchmarkRunner = { cells: {} }; -if (isInBrowser) { +if (JetStream.isInBrowser) { OfflineAssemblerBenchmarkRunner.cells = { firstIteration: document.getElementById("OfflineAssemblerFirstIteration"), averageWorstCase: document.getElementById("OfflineAssemblerAverageWorstCase"), diff --git a/RexBench/sunspider_benchmark.js b/RexBench/sunspider_benchmark.js index 34f8a9ae..e484aefd 100644 --- a/RexBench/sunspider_benchmark.js +++ b/RexBench/sunspider_benchmark.js @@ -39,7 +39,7 @@ reportResult(results); let runRegexDNABenchmark = null; -if (!isInBrowser) { +if (!JetStream.isInBrowser) { let sources = [ "benchmark.js" , "SunSpider/regex-dna.js" @@ -56,7 +56,7 @@ const RegexDNABenchmarkRunner = { cells: {} }; -if (isInBrowser) { +if (JetStream.isInBrowser) { RegexDNABenchmarkRunner.cells = { firstIteration: document.getElementById("RegexDNAFirstIteration"), averageWorstCase: document.getElementById("RegexDNAAverageWorstCase"), diff --git a/RexBench/unipoker_benchmark.js b/RexBench/unipoker_benchmark.js index ecb2010f..df7983a6 100644 --- a/RexBench/unipoker_benchmark.js +++ b/RexBench/unipoker_benchmark.js @@ -40,7 +40,7 @@ reportResult(results); let runUniPokerBenchmark = null; -if (!isInBrowser) { +if (!JetStream.isInBrowser) { let sources = [ "benchmark.js" , "UniPoker/poker.js" @@ -58,7 +58,7 @@ const UniPokerBenchmarkRunner = { cells: {} }; -if (isInBrowser) { +if (JetStream.isInBrowser) { UniPokerBenchmarkRunner.cells = { firstIteration: document.getElementById("UniPokerFirstIteration"), averageWorstCase: document.getElementById("UniPokerAverageWorstCase"), diff --git a/code-load/code-multi-load.js b/code-load/code-multi-load.js index 1f786b26..70a03c3b 100644 --- a/code-load/code-multi-load.js +++ b/code-load/code-multi-load.js @@ -26,7 +26,7 @@ let indirectEval = eval; class Benchmark { async init() { - this.inspectorText = `let _____top_level_____ = ${Math.random()}; ${await getString(inspectorPayloadBlob)}`; + this.inspectorText = `let _____top_level_____ = ${Math.random()}; ${await JetStream.getString(JetStream.preload.inspectorPayloadBlob)}`; this.index = 0; } diff --git a/wasm/tfjs-benchmark.js b/wasm/tfjs-benchmark.js index 0a9bf452..c19b3496 100644 --- a/wasm/tfjs-benchmark.js +++ b/wasm/tfjs-benchmark.js @@ -24,9 +24,9 @@ */ async function doRun() { - if (!isInBrowser) { - globalThis.tfjsBackendWasmSimdBlob = Module.tfjsBackendWasmSimdBlob; - globalThis.tfjsBackendWasmBlob = Module.tfjsBackendWasmBlob; + if (!JetStream.isInBrowser) { + JetStream.preload.tfjsBackendWasmSimdBlob = Module.tfjsBackendWasmSimdBlob; + JetStream.preload.tfjsBackendWasmBlob = Module.tfjsBackendWasmBlob; } let start = benchmarkTime(); diff --git a/wasm/tfjs-bundle.js b/wasm/tfjs-bundle.js index f98b6ff1..34a1bb36 100644 --- a/wasm/tfjs-bundle.js +++ b/wasm/tfjs-bundle.js @@ -23188,7 +23188,7 @@ }); } function instantiateAsync() { - if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { + if (!JetStream.preload.wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { return fetch(wasmBinaryFile, { credentials: "same-origin" }).then(function (response) { @@ -23218,7 +23218,6 @@ // console.warn("shell tfjs instantiating wasm backend"); } else console.warn("Fatal error: no binary file found for ./wasm/tfjs-backend-wasm-simd.wasm and ./wasm/tfjs-backend-wasm.wasm"); - WebAssembly.instantiate(blob, info).then(function (output) { receiveInstance(output.instance, output.module); }); diff --git a/worker/bomb.js b/worker/bomb.js index 911f9b8d..20672c3d 100644 --- a/worker/bomb.js +++ b/worker/bomb.js @@ -41,7 +41,7 @@ function startWorker(file) { } function startCycle() { - if (!isInBrowser) + if (!JetStream.isInBrowser) throw new Error("Only works in browser"); const tests = [ From c607c67170706c89e47d17deef41c4dce116bd04 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 13 Aug 2025 17:09:28 +0200 Subject: [PATCH 03/11] fix bomb-workers --- 8bitbench/benchmark.js | 2 +- Dart/benchmark.js | 3 +-- Dart/build/run_wasm.js | 3 +-- JetStreamDriver.js | 19 +++++++-------- wasm/dotnet/benchmark.js | 2 +- worker/bomb.js | 52 ++++++++++++++++++++-------------------- worker/segmentation.js | 2 +- 7 files changed, 40 insertions(+), 43 deletions(-) diff --git a/8bitbench/benchmark.js b/8bitbench/benchmark.js index 001efda9..cfc0639a 100644 --- a/8bitbench/benchmark.js +++ b/8bitbench/benchmark.js @@ -39,7 +39,7 @@ class Benchmark { async init() { Module.wasmBinary = await JetStream.getBinary(JetStream.preload.wasmBinary); - this.romBinary = await JetStream.getBinary(JetStream..preload.romBinary); + this.romBinary = await JetStream.getBinary(JetStream.preload.romBinary); } async runIteration() { diff --git a/Dart/benchmark.js b/Dart/benchmark.js index 37ebdcd3..10729a36 100644 --- a/Dart/benchmark.js +++ b/Dart/benchmark.js @@ -62,8 +62,7 @@ function addTaskQueue(self) { ms = Math.max(0, ms); var id = timerIdCounter++; // A callback can be scheduled at most once. - // (console.assert is only available on D8) - // if (isD8) console.assert(f.$timerId === undefined); + console.assert(f.$timerId === undefined); f.$timerId = id; timerIds[id] = f; if (ms == 0 && !isNextTimerDue()) { diff --git a/Dart/build/run_wasm.js b/Dart/build/run_wasm.js index 8b2eb936..4ee444f9 100644 --- a/Dart/build/run_wasm.js +++ b/Dart/build/run_wasm.js @@ -146,8 +146,7 @@ if (argsSplit != -1) { ms = Math.max(0, ms); var id = timerIdCounter++; // A callback can be scheduled at most once. - // (console.assert is only available on D8) - if (isD8) console.assert(f.$timerId === undefined); + console.assert(f.$timerId === undefined); f.$timerId = id; timerIds[id] = f; if (ms == 0 && !isNextTimerDue()) { diff --git a/JetStreamDriver.js b/JetStreamDriver.js index f028d66d..a5488906 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -633,9 +633,14 @@ class ShellScripts extends Scripts { globalObject.console = { log: globalObject.print, - warn: (e) => { print("Warn: " + e); }, - error: (e) => { print("Error: " + e); }, - debug: (e) => { print("Debug: " + e); }, + assert(condition, message) { + if (!condition) { + throw new Error(`Assertion failed: ${message}`); + } + }, + warn(e) { print("Warn: " + e); }, + error(e) { print("Error: " + e); }, + debug(e) { print("Debug: " + e); }, }; globalObject.self = globalObject; @@ -645,14 +650,8 @@ class ShellScripts extends Scripts { }; globalObject.performance ??= performance; - for (const script of this.scripts) { - try { + for (const script of this.scripts) globalObject.loadString(script); - } catch(e) { - console.log(script); - throw e; - } - } return isD8 ? realm : globalObject; } diff --git a/wasm/dotnet/benchmark.js b/wasm/dotnet/benchmark.js index ba8939f9..91b4d9b6 100644 --- a/wasm/dotnet/benchmark.js +++ b/wasm/dotnet/benchmark.js @@ -124,7 +124,7 @@ class Benchmark { ] }; - this.dotnet = (await JetStream.dynamicImport(JetStream.dotnetUrl)).dotnet; + this.dotnet = (await JetStream.dynamicImport(JetStream.preload.dotnetUrl)).dotnet; this.api = await this.dotnet.withModuleConfig({ locateFile: e => e }).withConfig(config).create(); this.exports = await this.api.getAssemblyExports("dotnet.dll"); diff --git a/worker/bomb.js b/worker/bomb.js index 20672c3d..350a5448 100644 --- a/worker/bomb.js +++ b/worker/bomb.js @@ -45,32 +45,32 @@ function startCycle() { throw new Error("Only works in browser"); const tests = [ - rayTrace3D - , accessNbody - , morph3D - , cube3D - , accessFunnkuch - , accessBinaryTrees - , accessNsieve - , bitopsBitwiseAnd - , bitopsNsieveBits - , controlflowRecursive - , bitops3BitBitsInByte - , botopsBitsInByte - , cryptoAES - , cryptoMD5 - , cryptoSHA1 - , dateFormatTofte - , dateFormatXparb - , mathCordic - , mathPartialSums - , mathSpectralNorm - , stringBase64 - , stringFasta - , stringValidateInput - , stringTagcloud - , stringUnpackCode - , regexpDNA + JetStream.preload.rayTrace3D, + JetStream.preload.accessNbody, + JetStream.preload.morph3D, + JetStream.preload.cube3D, + JetStream.preload.accessFunnkuch, + JetStream.preload.accessBinaryTrees, + JetStream.preload.accessNsieve, + JetStream.preload.bitopsBitwiseAnd, + JetStream.preload.bitopsNsieveBits, + JetStream.preload.controlflowRecursive, + JetStream.preload.bitops3BitBitsInByte, + JetStream.preload.botopsBitsInByte, + JetStream.preload.cryptoAES, + JetStream.preload.cryptoMD5, + JetStream.preload.cryptoSHA1, + JetStream.preload.dateFormatTofte, + JetStream.preload.dateFormatXparb, + JetStream.preload.mathCordic, + JetStream.preload.mathPartialSums, + JetStream.preload.mathSpectralNorm, + JetStream.preload.stringBase64, + JetStream.preload.stringFasta, + JetStream.preload.stringValidateInput, + JetStream.preload.stringTagcloud, + JetStream.preload.stringUnpackCode, + JetStream.preload.regexpDNA, ]; for (let test of tests) diff --git a/worker/segmentation.js b/worker/segmentation.js index 51fbdced..17d04e2f 100644 --- a/worker/segmentation.js +++ b/worker/segmentation.js @@ -560,7 +560,7 @@ class AsyncTaskWorker { constructor() { - this._webWorker = new Worker(asyncTaskBlob); + this._webWorker = new Worker(JetStream.preload.asyncTaskBlob); this._webWorker.onmessage = this._didRecieveMessage.bind(this); this._id = AsyncTaskWorker._workerId; this._startTime = Date.now(); From 8ed6c00d190582b561c03300c0f638582811590e Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 13 Aug 2025 18:09:02 +0200 Subject: [PATCH 04/11] more console functions --- JetStreamDriver.js | 14 ++------------ cli.js | 6 ++++-- shell-config.js | 23 +++++++++++++++++------ 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/JetStreamDriver.js b/JetStreamDriver.js index a5488906..f4e8e049 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -631,18 +631,8 @@ class ShellScripts extends Scripts { } else globalObject = runString(""); - globalObject.console = { - log: globalObject.print, - assert(condition, message) { - if (!condition) { - throw new Error(`Assertion failed: ${message}`); - } - }, - warn(e) { print("Warn: " + e); }, - error(e) { print("Error: " + e); }, - debug(e) { print("Debug: " + e); }, - }; - + assert(console, "Missing console object"); + globalObject.console = console; globalObject.self = globalObject; globalObject.top = { currentResolve, diff --git a/cli.js b/cli.js index b670d21e..2fdc1b4c 100644 --- a/cli.js +++ b/cli.js @@ -67,8 +67,10 @@ async function runJetStream() { await JetStream.initialize(); await JetStream.start(); } catch (e) { - console.error("JetStream3 failed: " + e); - console.error(e.stack); + console.error("JetStream3 failed:", e); + const stack = e.stack; + if (stack) + console.error(stack); throw e; } } diff --git a/shell-config.js b/shell-config.js index 8b29c7bf..4dfe9068 100644 --- a/shell-config.js +++ b/shell-config.js @@ -24,11 +24,22 @@ */ const isInBrowser = false; -console = { - log: globalThis?.console?.log ?? print, - error: globalThis?.console?.error ?? print, - warn: globalThis?.console?.warn ?? print, -} +if (typeof console == "undefined") + console = {} + +console.debug ??= (...args) => console.log("Debug:", ...args); +console.log ??= (...args) => print(args.join(" ")); +console.warn ??= (...args) => console.log("Warn:", ...args); +console.error ??= (...args) => console.log("Error:", ...args); +console.assert ??= (condition, message) => { + if (!condition) + throw new Error(`Assertion failed: ${message}`); +}; +console.trace ??= () => { + const targetObject = {}; + Error.captureStackTrace(targetObject); + console.log(targetObject.stack); +}; const isD8 = typeof Realm !== "undefined"; if (isD8) @@ -43,4 +54,4 @@ if (typeof performance == "undefined") performance = {}; performance.mark ??= function(){}; -performance.measure ??= function(){}; \ No newline at end of file +performance.measure ??= function(){}; From e7a9115d303af3402031e3027ff8d0f9875c3782 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 13 Aug 2025 18:19:07 +0200 Subject: [PATCH 05/11] fixes --- Kotlin-compose/benchmark.js | 1 + cli.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 7ae3f14e..3c15cd3e 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -60,6 +60,7 @@ globalThis.fetch = async function(url) { }, }; } + console.error("Shoudl not be called", url) // This should only be called in the browser, where fetch() is available. return originalFetch(url); diff --git a/cli.js b/cli.js index 2fdc1b4c..895469c7 100644 --- a/cli.js +++ b/cli.js @@ -74,7 +74,18 @@ async function runJetStream() { throw e; } } - +function getAllProperties(obj){ + var allProps = [] + , curr = obj + do{ + var props = Object.getOwnPropertyNames(curr) + props.forEach(function(prop){ + if (allProps.indexOf(prop) === -1) + allProps.push(prop) + }) + }while(curr = Object.getPrototypeOf(curr)) + return allProps +} load("./JetStreamDriver.js"); if ("--help" in cliFlags) { From e5c81e72c519af0bfb87d08f2bf3d2094f724b04 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 11:55:18 +0200 Subject: [PATCH 06/11] fixes --- JetStreamDriver.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/JetStreamDriver.js b/JetStreamDriver.js index 06cd118c..c2fbb77b 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -1307,28 +1307,26 @@ class WSLBenchmark extends Benchmark { const results = []; { - const benchmark = new Benchmark(); - const benchmarkName = "${this.name}"; + const markLabel = benchmarkName + "-stdlib"; + const startMark = performance.mark(markLabel); const start = performance.now(); benchmark.buildStdlib(); results.push(performance.now() - start); - let start = performance.now(); - benchmark.buildStdlib(); - results.push(performance.now() - start); + performance.measure(markLabel, markLabel); + } - performance.measure(markLabel, markLabel); - }; + { + const markLabel = benchmarkName + "-mainRun"; + const startMark = performance.mark(markLabel); const start = performance.now(); benchmark.run(); results.push(performance.now() - start); - let start = performance.now(); - benchmark.run(); - results.push(performance.now() - start); - + performance.measure(markLabel, markLabel); + } top.currentResolve(results); }`; } From 0992acf05a777ba8dab25b9f407eb31bd1313381 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 12:47:56 +0200 Subject: [PATCH 07/11] fixes --- JetStreamDriver.js | 41 ++++++++++++++++++------ Kotlin-compose/benchmark.js | 2 ++ RexBench/flightplan_benchmark.js | 4 +-- RexBench/flightplan_unicode_benchmark.js | 4 +-- RexBench/offline_assembler_benchmark.js | 4 +-- RexBench/sunspider_benchmark.js | 4 +-- RexBench/unipoker_benchmark.js | 4 +-- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/JetStreamDriver.js b/JetStreamDriver.js index c2fbb77b..5215010f 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -561,21 +561,28 @@ const BenchmarkState = Object.freeze({ class Scripts { constructor() { this.scripts = []; + // Expose a globalThis.JetStream object to the workload. We use + // a proxy to prevent prototype access and throw on unknown properties. this.add(` + const throwOnAccess = (name) => new Proxy({}, { + get(target, property, receiver) { + throw new Error(name + "." + property + " is not defined."); + } + }); globalThis.JetStream = { - isInBrowser: ${isInBrowser}, - isD8: ${isD8}, - preload: {}, + __proto__: throwOnAccess("JetStream"), + preload: { + __proto__: throwOnAccess("JetStream.preload"), + }, }; - if (typeof performance.mark === 'undefined') { - performance.mark = function(name) { return { name }}; - } - if (typeof performance.measure === 'undefined') { - performance.measure = function() {}; - } + `); + this.add(` + performance.mark ??= function(name) { return { name }}; + performance.measure ??= function() {}; `); } + run() { throw new Error("Subclasses need to implement this"); } @@ -588,6 +595,13 @@ class Scripts { throw new Error("addWithURL not supported"); } + addBrowserTest() { + this.add(` + globalThis.JetStream.isInBrowser = ${isInBrowser}; + globalThis.JetStream.isD8 = ${isD8}; + `); + } + addDeterministicRandom() { this.add(`(() => { const initialSeed = 49734321; @@ -799,6 +813,10 @@ class Benchmark { if (!!this.plan.deterministicRandom) scripts.addDeterministicRandom() + if (!!this.plan.exposeBrowserTest) { + console.log(this.name, "exposeBrowserTest") + scripts.addBrowserTest(); + } if (this.plan.preload) { let preloadCode = ""; @@ -1763,6 +1781,8 @@ let BENCHMARKS = [ "./RexBench/UniPoker/benchmark.js", ], deterministicRandom: true, + // FIXME: UniPoker should not access isInBrowser. + exposeBrowserTest: true, tags: ["Default", "RexBench"], }), // Simple @@ -2107,6 +2127,7 @@ let BENCHMARKS = [ }, async: true, deterministicRandom: true, + exposeBrowserTest: true, tags: ["Default", "Wasm"], }), new WasmLegacyBenchmark({ @@ -2127,6 +2148,7 @@ let BENCHMARKS = [ }, async: true, deterministicRandom: true, + exposeBrowserTest: true, tags: ["Default", "Wasm"], }), new WasmEMCCBenchmark({ @@ -2149,6 +2171,7 @@ let BENCHMARKS = [ files: [ "./worker/bomb.js", ], + exposeBrowserTest: true, iterations: 80, preload: { rayTrace3D: "./worker/bomb-subtests/3d-raytrace.js", diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 3c15cd3e..307af35b 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -7,6 +7,8 @@ globalThis.window ??= globalThis; +isD8 = false; + globalThis.navigator ??= {}; if (!globalThis.navigator.languages) { globalThis.navigator.languages = ['en-US', 'en']; diff --git a/RexBench/flightplan_benchmark.js b/RexBench/flightplan_benchmark.js index ef05ab3b..cb9e5534 100644 --- a/RexBench/flightplan_benchmark.js +++ b/RexBench/flightplan_benchmark.js @@ -42,7 +42,7 @@ reportResult(results); let runFlightPlannerBenchmark = null; -if (!JetStream.isInBrowser) { +if (!isInBrowser) { let sources = [ "benchmark.js" , "FlightPlanner/airways.js" @@ -62,7 +62,7 @@ const FlightPlannerBenchmarkRunner = { cells: {} }; -if (JetStream.isInBrowser) { +if (isInBrowser) { FlightPlannerBenchmarkRunner.cells = { firstIteration: document.getElementById("FlightPlannerFirstIteration"), averageWorstCase: document.getElementById("FlightPlannerAverageWorstCase"), diff --git a/RexBench/flightplan_unicode_benchmark.js b/RexBench/flightplan_unicode_benchmark.js index 838b0ad6..f30e38e3 100644 --- a/RexBench/flightplan_unicode_benchmark.js +++ b/RexBench/flightplan_unicode_benchmark.js @@ -43,7 +43,7 @@ reportResult(results); let runFlightPlannerUnicodeBenchmark = null; -if (!JetStream.isInBrowser) { +if (!isInBrowser) { let sources = [ "benchmark.js" , "FlightPlanner/airways.js" @@ -64,7 +64,7 @@ const FlightPlannerUnicodeBenchmarkRunner = { cells: {} }; -if (JetStream.isInBrowser) { +if (isInBrowser) { FlightPlannerUnicodeBenchmarkRunner.cells = { firstIteration: document.getElementById("FlightPlannerUnicodeFirstIteration"), averageWorstCase: document.getElementById("FlightPlannerUnicodeAverageWorstCase"), diff --git a/RexBench/offline_assembler_benchmark.js b/RexBench/offline_assembler_benchmark.js index 998944f7..61240531 100644 --- a/RexBench/offline_assembler_benchmark.js +++ b/RexBench/offline_assembler_benchmark.js @@ -48,7 +48,7 @@ reportResult(results); let runOfflineAssemblerBenchmark = null; -if (!JetStream.isInBrowser) { +if (!isInBrowser) { let sources = [ "benchmark.js" , "OfflineAssembler/registers.js" @@ -74,7 +74,7 @@ const OfflineAssemblerBenchmarkRunner = { cells: {} }; -if (JetStream.isInBrowser) { +if (isInBrowser) { OfflineAssemblerBenchmarkRunner.cells = { firstIteration: document.getElementById("OfflineAssemblerFirstIteration"), averageWorstCase: document.getElementById("OfflineAssemblerAverageWorstCase"), diff --git a/RexBench/sunspider_benchmark.js b/RexBench/sunspider_benchmark.js index e484aefd..34f8a9ae 100644 --- a/RexBench/sunspider_benchmark.js +++ b/RexBench/sunspider_benchmark.js @@ -39,7 +39,7 @@ reportResult(results); let runRegexDNABenchmark = null; -if (!JetStream.isInBrowser) { +if (!isInBrowser) { let sources = [ "benchmark.js" , "SunSpider/regex-dna.js" @@ -56,7 +56,7 @@ const RegexDNABenchmarkRunner = { cells: {} }; -if (JetStream.isInBrowser) { +if (isInBrowser) { RegexDNABenchmarkRunner.cells = { firstIteration: document.getElementById("RegexDNAFirstIteration"), averageWorstCase: document.getElementById("RegexDNAAverageWorstCase"), diff --git a/RexBench/unipoker_benchmark.js b/RexBench/unipoker_benchmark.js index df7983a6..ecb2010f 100644 --- a/RexBench/unipoker_benchmark.js +++ b/RexBench/unipoker_benchmark.js @@ -40,7 +40,7 @@ reportResult(results); let runUniPokerBenchmark = null; -if (!JetStream.isInBrowser) { +if (!isInBrowser) { let sources = [ "benchmark.js" , "UniPoker/poker.js" @@ -58,7 +58,7 @@ const UniPokerBenchmarkRunner = { cells: {} }; -if (JetStream.isInBrowser) { +if (isInBrowser) { UniPokerBenchmarkRunner.cells = { firstIteration: document.getElementById("UniPokerFirstIteration"), averageWorstCase: document.getElementById("UniPokerAverageWorstCase"), From fe2e8d82b514dc3735b3187c22260099c603179f Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 12:49:09 +0200 Subject: [PATCH 08/11] revert --- Kotlin-compose/benchmark.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 307af35b..50125bb2 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -7,8 +7,6 @@ globalThis.window ??= globalThis; -isD8 = false; - globalThis.navigator ??= {}; if (!globalThis.navigator.languages) { globalThis.navigator.languages = ['en-US', 'en']; @@ -62,7 +60,6 @@ globalThis.fetch = async function(url) { }, }; } - console.error("Shoudl not be called", url) // This should only be called in the browser, where fetch() is available. return originalFetch(url); @@ -115,20 +112,20 @@ class Benchmark { // console.log("init"); preload = { - 'skiko.wasm': await JetStream.getBinary(JetStream.preload.skikoWasmBinary), - './compose-benchmarks-benchmarks.wasm': await JetStream.getBinary(JetStream.preload.composeWasmBinary), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await JetStream.getBinary(JetStream.preload.inputImageCompose), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await JetStream.getBinary(JetStream.preload.inputImageCat), - './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await JetStream.getBinary(JetStream.preload.inputImageComposeCommunity), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await JetStream.getBinary(JetStream.preload.inputFontItalic), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await JetStream.getBinary(JetStream.preload.inputFontRegular), + 'skiko.wasm': await getBinary(skikoWasmBinary), + './compose-benchmarks-benchmarks.wasm': await getBinary(composeWasmBinary), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await getBinary(inputImageCompose), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await getBinary(inputImageCat), + './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await getBinary(inputImageComposeCommunity), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await getBinary(inputFontItalic), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await getBinary(inputFontRegular), }; // We patched `skiko.mjs` to not immediately instantiate the `skiko.wasm` // module, so that we can move the dynamic JS import here but measure // WebAssembly compilation and instantiation as part of the first iteration. - this.skikoInstantiate = (await JetStream.dynamicImport(JetStream.preload.skikoJsModule)).default; - this.mainInstantiate = (await JetStream.dynamicImport(JetStream.preload.composeJsModule)).instantiate; + this.skikoInstantiate = (await dynamicImport(skikoJsModule)).default; + this.mainInstantiate = (await dynamicImport(composeJsModule)).instantiate; } async runIteration() { From 9a2b9214857ace3978e297d32728ec6a2dc6e553 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 12:53:45 +0200 Subject: [PATCH 09/11] cleanup --- Dart/build/run_wasm.js | 3 ++- JetStreamDriver.js | 33 +++++++++++++++------------------ cli.js | 19 +++---------------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/Dart/build/run_wasm.js b/Dart/build/run_wasm.js index 4ee444f9..8b2eb936 100644 --- a/Dart/build/run_wasm.js +++ b/Dart/build/run_wasm.js @@ -146,7 +146,8 @@ if (argsSplit != -1) { ms = Math.max(0, ms); var id = timerIdCounter++; // A callback can be scheduled at most once. - console.assert(f.$timerId === undefined); + // (console.assert is only available on D8) + if (isD8) console.assert(f.$timerId === undefined); f.$timerId = id; timerIds[id] = f; if (ms == 0 && !isNextTimerDue()) { diff --git a/JetStreamDriver.js b/JetStreamDriver.js index c3d96a45..1fcf87c0 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -813,10 +813,8 @@ class Benchmark { if (!!this.plan.deterministicRandom) scripts.addDeterministicRandom() - if (!!this.plan.exposeBrowserTest) { - console.log(this.name, "exposeBrowserTest") + if (!!this.plan.exposeBrowserTest) scripts.addBrowserTest(); - } if (this.plan.preload) { let preloadCode = ""; @@ -1269,6 +1267,7 @@ class WasmEMCCBenchmark extends AsyncBenchmark { get prerunCode() { let str = ` let verbose = false; + let globalObject = this; abort = quit = function() { @@ -1276,23 +1275,21 @@ class WasmEMCCBenchmark extends AsyncBenchmark { console.log('Intercepted quit/abort'); }; - { - const oldPrint = globalObject.print; - globalObject.print = globalObject.printErr = (...args) => { - if (verbose) - console.log('Intercepted print: ', ...args); - }; - - let Module = { - preRun: [], - postRun: [], - noInitialRun: true, - print: print, - printErr: printErr - }; + const oldPrint = globalObject.print; + globalObject.print = globalObject.printErr = (...args) => { + if (verbose) + console.log('Intercepted print: ', ...args); + }; - globalObject.Module = Module; + let Module = { + preRun: [], + postRun: [], + noInitialRun: true, + print: print, + printErr: printErr }; + + globalObject.Module = Module; ${super.prerunCode}; `; diff --git a/cli.js b/cli.js index 9a54864c..5429ccd8 100644 --- a/cli.js +++ b/cli.js @@ -67,25 +67,12 @@ async function runJetStream() { await JetStream.initialize(); await JetStream.start(); } catch (e) { - console.error("JetStream3 failed:", e); - const stack = e.stack; - if (stack) - console.error(stack); + console.error("JetStream3 failed: " + e); + console.error(e.stack); throw e; } } -function getAllProperties(obj){ - var allProps = [] - , curr = obj - do{ - var props = Object.getOwnPropertyNames(curr) - props.forEach(function(prop){ - if (allProps.indexOf(prop) === -1) - allProps.push(prop) - }) - }while(curr = Object.getPrototypeOf(curr)) - return allProps -} + load("./JetStreamDriver.js"); if ("--help" in cliFlags) { From 29a937ad10e829d8fcbe376926b9dc9cf4b002ca Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 12:54:15 +0200 Subject: [PATCH 10/11] more cleanup --- JetStreamDriver.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/JetStreamDriver.js b/JetStreamDriver.js index 1fcf87c0..c638a612 100644 --- a/JetStreamDriver.js +++ b/JetStreamDriver.js @@ -1401,21 +1401,19 @@ class WasmLegacyBenchmark extends Benchmark { console.log('Intercepted quit/abort'); }; - { - const oldConsoleLog = globalObject.console.log; - globalObject.print = globalObject.printErr = (...args) => { - if (verbose) - oldConsoleLog('Intercepted print: ', ...args); - }; + const oldConsoleLog = globalObject.console.log; + globalObject.print = globalObject.printErr = (...args) => { + if (verbose) + oldConsoleLog('Intercepted print: ', ...args); + }; - let Module = { - preRun: [], - postRun: [], - print: globalObject.print, - printErr: globalObject.print - }; - globalObject.Module = Module; + let Module = { + preRun: [], + postRun: [], + print: globalObject.print, + printErr: globalObject.print }; + globalObject.Module = Module; `; return str; } From 6f0fec489bac2a706af2fba90909e52a7b77cef2 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 14 Aug 2025 18:25:58 +0200 Subject: [PATCH 11/11] fix kotlin workload --- Kotlin-compose/benchmark.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Kotlin-compose/benchmark.js b/Kotlin-compose/benchmark.js index 50125bb2..7ae3f14e 100644 --- a/Kotlin-compose/benchmark.js +++ b/Kotlin-compose/benchmark.js @@ -112,20 +112,20 @@ class Benchmark { // console.log("init"); preload = { - 'skiko.wasm': await getBinary(skikoWasmBinary), - './compose-benchmarks-benchmarks.wasm': await getBinary(composeWasmBinary), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await getBinary(inputImageCompose), - './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await getBinary(inputImageCat), - './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await getBinary(inputImageComposeCommunity), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await getBinary(inputFontItalic), - './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await getBinary(inputFontRegular), + 'skiko.wasm': await JetStream.getBinary(JetStream.preload.skikoWasmBinary), + './compose-benchmarks-benchmarks.wasm': await JetStream.getBinary(JetStream.preload.composeWasmBinary), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/compose-multiplatform.png': await JetStream.getBinary(JetStream.preload.inputImageCompose), + './composeResources/compose_benchmarks.benchmarks.generated.resources/drawable/example1_cat.jpg': await JetStream.getBinary(JetStream.preload.inputImageCat), + './composeResources/compose_benchmarks.benchmarks.generated.resources/files/example1_compose-community-primary.png': await JetStream.getBinary(JetStream.preload.inputImageComposeCommunity), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_italic.ttf': await JetStream.getBinary(JetStream.preload.inputFontItalic), + './composeResources/compose_benchmarks.benchmarks.generated.resources/font/jetbrainsmono_regular.ttf': await JetStream.getBinary(JetStream.preload.inputFontRegular), }; // We patched `skiko.mjs` to not immediately instantiate the `skiko.wasm` // module, so that we can move the dynamic JS import here but measure // WebAssembly compilation and instantiation as part of the first iteration. - this.skikoInstantiate = (await dynamicImport(skikoJsModule)).default; - this.mainInstantiate = (await dynamicImport(composeJsModule)).instantiate; + this.skikoInstantiate = (await JetStream.dynamicImport(JetStream.preload.skikoJsModule)).default; + this.mainInstantiate = (await JetStream.dynamicImport(JetStream.preload.composeJsModule)).instantiate; } async runIteration() {