Offload functions to worker threads with shared memory primitives for Node.js.
1// Measures roundtrip channel throughput (main → worker → main) with
2// 1 up to availableParallelism() workers. The worker is a passthrough
3// streaming moroutine that yields each item back unchanged.
4// Requires Node v24+.
5//
6// Run: node examples/benchmark/main.ts
7
8import { availableParallelism } from 'node:os';
9import { workers, channel } from '../../src/index.ts';
10import { passthrough } from './work.ts';
11
12const ITEMS = 100_000;
13const MAX_WORKERS = availableParallelism();
14
15async function bench(numWorkers: number): Promise<number> {
16 async function* source() {
17 for (let i = 0; i < ITEMS; i++) yield i;
18 }
19
20 const data = channel(source());
21
22 using run = workers(numWorkers);
23 const tasks = Array.from({ length: numWorkers }, () => passthrough(data));
24 const streams = tasks.map((t) => run(t));
25
26 const start = performance.now();
27 let count = 0;
28 await Promise.all(
29 streams.map(async (s) => {
30 for await (const _ of s) count++;
31 }),
32 );
33 const elapsed = performance.now() - start;
34
35 return count / (elapsed / 1000);
36}
37
38console.log(`Roundtrip throughput: ${ITEMS.toLocaleString()} items, 1–${MAX_WORKERS} workers\n`);
39
40for (let n = 1; n <= MAX_WORKERS; n++) {
41 const ips = await bench(n);
42 const bar = '#'.repeat(Math.round(ips / 1000));
43 console.log(
44 ` ${String(n).padStart(2)} worker${n === 1 ? ' ' : 's'} ${Math.round(ips).toLocaleString().padStart(8)} items/s ${bar}`,
45 );
46}