From harness-claude
Offloads CPU-intensive tasks to Node.js worker threads using MessageChannel, shared buffers, pools, and SharedArrayBuffer for parallel computation without blocking the event loop.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Offload CPU-intensive work to worker threads using MessageChannel and shared buffers
Implements Web Workers and Node.js worker_threads in Bun for parallel processing, transferable objects, shared memory, and worker pools.
Implements Web Workers for off-main-thread computation: dedicated workers, Comlink RPC, SharedArrayBuffer sharing, pooling, React/bundler patterns. Use for CPU tasks like sorting, filtering, image processing to prevent UI jank.
Provides bash patterns for parallel and concurrent processing using GNU Parallel, xargs, job pools, worker control, and async techniques to accelerate batch tasks.
Share bugs, ideas, or general feedback.
Offload CPU-intensive work to worker threads using MessageChannel and shared buffers
// main.ts
import { Worker } from 'node:worker_threads';
const worker = new Worker('./worker.ts', {
workerData: { input: [1, 2, 3, 4, 5] },
});
worker.on('message', (result) => {
console.log('Result:', result);
});
worker.on('error', (err) => {
console.error('Worker error:', err);
});
worker.on('exit', (code) => {
if (code !== 0) console.error(`Worker exited with code ${code}`);
});
// worker.ts
import { parentPort, workerData } from 'node:worker_threads';
const result = workerData.input.map((n: number) => n * n);
parentPort?.postMessage(result);
function runWorker<T>(workerPath: string, data: unknown): Promise<T> {
return new Promise((resolve, reject) => {
const worker = new Worker(workerPath, { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0) reject(new Error(`Worker exited with code ${code}`));
});
});
}
const result = await runWorker<number[]>('./worker.ts', { input: data });
import { Worker } from 'node:worker_threads';
import os from 'node:os';
class WorkerPool {
private workers: Worker[] = [];
private queue: Array<{ data: unknown; resolve: Function; reject: Function }> = [];
private available: Worker[] = [];
constructor(
private workerPath: string,
size = os.cpus().length
) {
for (let i = 0; i < size; i++) {
const worker = new Worker(workerPath);
worker.on('message', (result) => {
this.available.push(worker);
this.processQueue();
});
this.workers.push(worker);
this.available.push(worker);
}
}
exec<T>(data: unknown): Promise<T> {
return new Promise((resolve, reject) => {
this.queue.push({ data, resolve, reject });
this.processQueue();
});
}
private processQueue() {
while (this.queue.length > 0 && this.available.length > 0) {
const worker = this.available.pop()!;
const { data, resolve } = this.queue.shift()!;
worker.once('message', resolve);
worker.postMessage(data);
}
}
async destroy() {
await Promise.all(this.workers.map((w) => w.terminate()));
}
}
// Share a buffer between main thread and worker
const sharedBuffer = new SharedArrayBuffer(1024);
const sharedArray = new Int32Array(sharedBuffer);
const worker = new Worker('./worker.ts', {
workerData: { buffer: sharedBuffer },
});
// Worker can read/write sharedArray directly — no serialization
const buffer = new ArrayBuffer(1024 * 1024); // 1MB
worker.postMessage({ buffer }, [buffer]); // Transfer, not copy
// buffer is now detached in the main thread
Worker threads run JavaScript in parallel OS threads within the same Node.js process. They share memory space but have separate V8 instances and event loops.
Worker threads vs child processes:
Communication overhead: postMessage serializes data using the structured clone algorithm. For large objects, this serialization can be slower than the computation itself. Use SharedArrayBuffer or transferable objects to avoid copying.
Trade-offs:
https://nodejs.org/api/worker_threads.html