Step 1 of the GC effort. Each tier loader now exposes heapStats():
- asm-wasm — lumbda_heap_used / lumbda_heap_total wat exports
- c-wasm — emscripten linear memory size (no free path right now,
so used = total; documented in the loader)
- python — pyodide module linear memory size; CPython GC cycles
this naturally
Worker handles a "heap" message kind that round-trips the active tab's
loaded tiers; repl tabbar shows a compact "py 12M · c 32M · asm 4M"
strip next to the buttons. Polls every 2s.
Doesn't solve the leak — just makes pressure visible so the user knows
when to use "reboot tier". Real GC (Cheney over the WAT bump allocator,
Boehm-em or custom mark-sweep for c-wasm) coming next.
30 lines
1.2 KiB
JavaScript
30 lines
1.2 KiB
JavaScript
// wasm/app/worker.mjs
|
|
// Tier-evaluation Web Worker. Keeps the main thread responsive so the
|
|
// live ms counter actually ticks AND so cancel works (main thread
|
|
// terminates this worker via worker.terminate()).
|
|
|
|
import { evalOnTier, setBendUrl, heapStats } from "./runner.js";
|
|
|
|
self.onmessage = async (e) => {
|
|
const { kind } = e.data;
|
|
if (kind === "config") {
|
|
setBendUrl(e.data.bendUrl);
|
|
return;
|
|
}
|
|
if (kind === "heap") {
|
|
// Synchronous read — no eval is running because the worker is
|
|
// single-threaded and main thread only sends this between evals.
|
|
self.postMessage({ kind: "heap", runId: e.data.runId, tier: e.data.tier, stats: heapStats(e.data.tier) });
|
|
return;
|
|
}
|
|
if (kind !== "eval") return;
|
|
const { runId, tier, src } = e.data;
|
|
try {
|
|
const output = await evalOnTier(tier, src, (loadingTier) => {
|
|
self.postMessage({ kind: "loading", runId, tier: loadingTier });
|
|
});
|
|
self.postMessage({ kind: "done", runId, output });
|
|
} catch (err) {
|
|
self.postMessage({ kind: "error", runId, message: err && err.message ? err.message : String(err) });
|
|
}
|
|
};
|