diff --git a/build.js b/build.js
index a9373d6..8f59ea5 100755
--- a/build.js
+++ b/build.js
@@ -136,7 +136,7 @@ if (watch) {
}
}).listen(8080);
- console.log("listening on port 8080");
+ console.log("listening on http://localhost:8080");
const webCtx = await esbuild.context(webBuildOptions);
webCtx.watch();
diff --git a/src/benchmarks/benchmarks.js b/src/benchmarks/benchmarks.js
index 4d1c60a..2797770 100644
--- a/src/benchmarks/benchmarks.js
+++ b/src/benchmarks/benchmarks.js
@@ -1,29 +1,29 @@
-import mandelbrot from "./mandelbrot.tal";
import Uxn from "../uxn";
+import suite from "./suite";
const DEV_OFFSET = 0x10200;
-const PROGRAM_OFFSET = 0x100;
document.body.innerHTML = `
Uxn.wasm Benchmarks
-
-
+
`;
const startButtonEl = document.getElementById("startButton");
-const mandelbrotResultsEl = document.getElementById("mandelbrotResults");
+const resultsEl = document.getElementById("results");
-function runMandelbrot(uxn) {
- uxn.load(mandelbrot);
- uxn.eval(PROGRAM_OFFSET);
-}
+startButtonEl.onclick = async () => {
+ startButtonEl.disabled = true;
+ resultsEl.replaceChildren();
+ for (const b of suite) {
+ const trEl = document.createElement("table");
+ resultsEl.appendChild(trEl);
+ const thEl = document.createElement("th");
+ thEl.appendChild(document.createTextNode(b.name));
+ trEl.appendChild(thEl);
-async function runMandelbrotBenchmark() {
- try {
- startButtonEl.disabled = true;
const uxn = new Uxn();
await uxn.init({
deo: () => {},
@@ -31,21 +31,25 @@ async function runMandelbrotBenchmark() {
return uxn.ram[DEV_OFFSET + port];
},
});
- mandelbrotResultsEl.innerHTML = "Mandelbrot | ";
+
for (let i = 0; i < 5; i++) {
- const el = document.createElement("td");
- mandelbrotResultsEl.appendChild(el);
- el.appendChild(document.createTextNode("⌛️"));
- const t1 = performance.now();
- runMandelbrot(uxn);
- const t2 = performance.now();
- el.innerHTML = ((t2 - t1) / 1000.0).toFixed(2) + "s";
+ const tdEl = document.createElement("td");
+ const valueEl = document.createTextNode("⌛️");
+ tdEl.appendChild(valueEl);
+ trEl.appendChild(tdEl);
+ let value;
+
+ try {
+ const t1 = performance.now();
+ b.run(uxn);
+ const t2 = performance.now();
+ value = ((t2 - t1) / 1000.0).toFixed(2) + "s";
+ } catch (e) {
+ console.error(e);
+ value = "error: " + e;
+ }
+ tdEl.replaceChild(document.createTextNode(value), valueEl);
}
- } finally {
- startButtonEl.disabled = false;
}
-}
-
-startButtonEl.onclick = () => {
- runMandelbrotBenchmark();
+ startButtonEl.disabled = false;
};
diff --git a/src/benchmarks/benchmarks.node.js b/src/benchmarks/benchmarks.node.js
new file mode 100644
index 0000000..d6fe2f4
--- /dev/null
+++ b/src/benchmarks/benchmarks.node.js
@@ -0,0 +1,25 @@
+const suite = require("./suite").default;
+const Uxn = require("../uxn");
+
+const DEV_OFFSET = 0x10200;
+
+(async () => {
+ const uxn = new Uxn();
+ await uxn.init({
+ deo: () => {},
+ dei: (port) => {
+ return uxn.ram[DEV_OFFSET + port];
+ },
+ });
+ for (const b of suite) {
+ console.log(b.name);
+ for (let i = 0; i < 5; i++) {
+ let value;
+ const t1 = performance.now();
+ b.run(uxn);
+ const t2 = performance.now();
+ value = ((t2 - t1) / 1000.0).toFixed(2) + "s";
+ console.log(` run ${i + 1}: ` + value);
+ }
+ }
+})();
diff --git a/src/benchmarks/suite.js b/src/benchmarks/suite.js
new file mode 100644
index 0000000..710a41c
--- /dev/null
+++ b/src/benchmarks/suite.js
@@ -0,0 +1,13 @@
+import mandelbrot from "./mandelbrot.tal";
+
+const PROGRAM_OFFSET = 0x100;
+
+export default [
+ {
+ name: "mandelbrot",
+ run: (uxn) => {
+ uxn.load(mandelbrot);
+ uxn.eval(PROGRAM_OFFSET);
+ },
+ },
+];
diff --git a/test.js b/test.js
index ebc7d86..1893f32 100755
--- a/test.js
+++ b/test.js
@@ -8,11 +8,15 @@ const { uxntalPlugin } = require("./scripts/esbuild/uxntal");
const Mocha = require("mocha");
let watch = false;
+let benchmarks = false;
for (const arg of process.argv.slice(2)) {
switch (arg) {
case "--watch":
watch = true;
break;
+ case "--benchmarks":
+ benchmarks = true;
+ break;
}
}
@@ -26,7 +30,6 @@ function runTests() {
const buildOptions = {
bundle: true,
logLevel: "warning",
- entryPoints: [path.join(__dirname, "src", "tests", "tests.node")],
target: "node17",
outdir: path.join(__dirname, "build"),
external: ["fs", "stream", "util", "events", "path"],
@@ -36,11 +39,15 @@ const buildOptions = {
".rom": "binary",
},
sourcemap: true,
- plugins: [
- wasmTextPlugin({ debug: true }),
- uxntalPlugin(),
+ plugins: [wasmTextPlugin({ debug: true }), uxntalPlugin()],
+};
+
+const testBuildOptions = {
+ ...buildOptions,
+ entryPoints: [path.join(__dirname, "src", "tests", "tests.node")],
+ plugins: buildOptions.plugins.concat([
{
- name: "watch",
+ name: "runTests",
setup(build) {
build.onEnd((result) => {
if (result.errors.length > 0) {
@@ -50,14 +57,37 @@ const buildOptions = {
});
},
},
- ],
+ ]),
};
-if (watch) {
- (async () => {
- const ctx = await esbuild.context(buildOptions);
- ctx.watch();
- })();
+const benchmarkBuildOptions = {
+ ...buildOptions,
+ entryPoints: [path.join(__dirname, "src", "benchmarks", "benchmarks.node")],
+ plugins: buildOptions.plugins.concat([
+ {
+ name: "runBenchmarks",
+ setup(build) {
+ build.onEnd((result) => {
+ if (result.errors.length > 0) {
+ return;
+ }
+ delete require.cache[path.join(__dirname, "build", "benchmarks.js")];
+ require("./build/benchmarks.js");
+ });
+ },
+ },
+ ]),
+};
+
+if (benchmarks) {
+ esbuild.build(benchmarkBuildOptions);
} else {
- esbuild.build(buildOptions);
+ if (watch) {
+ (async () => {
+ const ctx = await esbuild.context(testBuildOptions);
+ ctx.watch();
+ })();
+ } else {
+ esbuild.build(testBuildOptions);
+ }
}