Skip to content

Commit a87b922

Browse files
rustyconoverclaude
andcommitted
test(wasm-worker): TS worker true-parallelism proof (peakConcurrency=4)
test-ts-worker.mjs: scan ts_probe (maxWorkers=4) once under threads=4 — one scan fans out across N worker: connections => N slots => N dedicated SLOT sub-Workers, each CPU-busy- looping under a shared concurrency guard — then read ts_peek. Assert peak >= 2 (observed 4). Since a busy loop blocks a single async event loop (peak would be 1), this proves the TS SAB worker serves N slots on real parallel threads, matching the Rust worker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S2jkoYMNsNYkcpSh6Fwk2c
1 parent 13dcce5 commit a87b922

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

test/support/wasm-worker/browser-e2e/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,12 @@ mbedtls, but the disk tier is off on WASM — no persistent FS.)
145145
The `worker:` transport is worker-language-agnostic. `test-ts-worker.mjs` proves a
146146
**TypeScript** worker (vgi-typescript) serves over the same SAB channel at parity with
147147
the Rust `sabtable` worker: a direct `vgi_table_function('worker:ts-worker-boot.js',
148-
'ts_count', [5])` (producer mode), `ATTACH` + discovery + `tcat.main.ts_count(3)`, and a
149-
`ts_double` scalar (exchange mode). The worker is
150-
`vgi-typescript/examples/sab-worker/boot.ts` — it multiplexes all SAB slots on one Web
151-
Worker's event loop via `Atomics.waitAsync` (vs. the Rust worker's emscripten
152-
thread-per-slot) and drives vgi-rpc's `serveStream` over a new browser `ByteSink` writer.
148+
'ts_count', [5])` (producer mode), `ATTACH` + discovery + `tcat.main.ts_count(3)`, a
149+
`ts_double` scalar (exchange mode), and a **true-parallelism** proof (`peakConcurrency=4`
150+
`ts_probe`/`ts_peek`). The worker is `vgi-typescript/examples/sab-worker/boot.ts` — it
151+
drives vgi-rpc's `serveStream` over a browser `ByteSink` writer and is **truly parallel**:
152+
one dedicated sub-Worker per SAB slot (real threads sharing the SAB), matching the Rust
153+
worker's emscripten thread-per-slot.
153154

154155
```bash
155156
# build the TS worker bundle (from vgi-typescript), copy to ts-worker-mod.js here:

test/support/wasm-worker/browser-e2e/test-ts-worker.mjs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,21 @@ const to = (ms, t) => new Promise((_, rej) => setTimeout(() => rej(new Error('__
5454
log('ts_count(3)=' + JSON.stringify(cv) + ' ok=' + R.attachTableOk + '; ts_double=' + JSON.stringify(sv) + ' ok=' + R.scalarOk);
5555
} catch (e) { R.attachTableOk = false; R.scalarOk = false; R.attachErr = String(e.message || e).slice(0, 160); log('attach ERR ' + R.attachErr); }
5656

57+
// 3. TRUE PARALLELISM proof. ts_probe (maxWorkers=4) fans ONE scan across DuckDB scan
58+
// threads => N worker: connections => N slots => N dedicated SLOT sub-Workers, each
59+
// CPU-busy-looping under a shared concurrency guard. On a single async event loop the
60+
// busy loop blocks => peak concurrency 1; N real sub-Worker threads => peak >= 2.
61+
try {
62+
await q('SET threads=4');
63+
await q(`SELECT count(*)::INT FROM vgi_table_function(${W}, 'ts_probe', [200])`, 30000);
64+
const rp = await q(`SELECT * FROM vgi_table_function(${W}, 'ts_peek', [])`);
65+
R.peakConcurrency = Number(rp.getChildAt(0).get(0));
66+
R.parallelOk = R.peakConcurrency >= 2;
67+
log('peakConcurrency=' + R.peakConcurrency + ' parallelOk=' + R.parallelOk);
68+
} catch (e) { R.parallelOk = false; R.parallelErr = String(e.message || e).slice(0, 160); log('parallel ERR ' + R.parallelErr); }
69+
5770
await conn.close(); await db.terminate();
58-
R.pass = R.loaded && R.directOk && R.attachTableOk && R.scalarOk;
71+
R.pass = R.loaded && R.directOk && R.attachTableOk && R.scalarOk && R.parallelOk;
5972
log('PASS=' + R.pass);
6073
} catch (e) {
6174
R.error = String(e && e.stack ? e.stack : e); log('ERROR: ' + R.error);

0 commit comments

Comments
 (0)