Claude-skill-registry js-worker-multithreading
Implement, refactor, or review worker-based multithreading in TypeScript/JavaScript apps (browser or Node). Use when offloading CPU-heavy loops to Web Workers, setting up a worker pool, moving data across threads, or diagnosing worker crashes, slowdowns, or synchronization bugs.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/js-worker-multithreading" ~/.claude/skills/majiayu000-claude-skill-registry-js-worker-multithreading && rm -rf "$T"
manifest:
skills/data/js-worker-multithreading/SKILL.mdsource content
JS Worker Multithreading
Overview
Use this skill to move CPU-heavy work off the main thread with worker pools while keeping the main thread as the source of truth for UI, DOM, and physics APIs.
Workflow
- Identify the hot loop and define a pure worker kernel that takes plain data and returns plain data.
- Snapshot state into typed arrays or plain objects suitable for structured clone or transfer.
- Spawn a worker job, join for the result, and apply the result on the main thread.
- Gate jobs to avoid overlapping work and apply the latest completed result on the next tick.
- Add fallback behavior if workers or shared memory are not available.
Do
- Keep worker code pure (numeric math, no DOM, no Three.js, no physics APIs).
- Use typed arrays for bulk data and pass them with a transfer or move helper.
- Preallocate and reuse buffers to avoid per-frame allocations and GC spikes.
- Limit concurrent jobs; keep at most one in flight per simulation loop or queue with backpressure.
- Apply results on the main thread and keep authoritative state there.
- Catch worker failures, log them, and degrade gracefully (main-thread fallback).
- Detect SharedArrayBuffer and crossOriginIsolated before relying on shared memory.
- Initialize the worker runtime once; handle "already initialized" errors safely.
- Size the pool based on hardwareConcurrency and clamp to a safe range.
Do Not
- Do not call main-thread-only APIs (DOM, WebGL, Rapier, AudioContext) inside workers.
- Do not spawn a new worker per frame; reuse a pool or runtime.
- Do not pass class instances or engine objects across the worker boundary.
- Do not mutate shared state without explicit synchronization primitives.
- Do not launch overlapping jobs that race to apply results.
- Do not assume SharedArrayBuffer is available without COOP/COEP headers.
- Do not ignore failed worker results; disable or fallback to avoid infinite retries.
Minimal Template (multithreading package)
import { initRuntime, move, spawn } from 'multithreading'; type Input = { count: number; positions: Float32Array }; type Output = { forces: Float32Array }; function simulateStep(input: Input): Output { // Pure math only. const forces = new Float32Array(input.count * 3); return { forces }; } let runtimeReady = false; let jobInFlight = false; let pending: Output | null = null; function ensureRuntime() { if (runtimeReady) return; initRuntime({ maxWorkers: 4 }); runtimeReady = true; } async function tick(input: Input) { if (pending) { // Apply pending results on main thread here. pending = null; } if (jobInFlight) return; ensureRuntime(); jobInFlight = true; const handle = spawn(move(input), simulateStep); const result = await handle.join(); jobInFlight = false; if (result.ok) { pending = result.value; } else { // Log and fallback to main-thread compute if needed. } }
Troubleshooting Checklist
- Verify the worker kernel only uses serializable inputs and outputs.
- Confirm large arrays are transferred, not cloned.
- Ensure the main thread applies results in a deterministic order.
- Log worker failures and guard against repeated crashes.
- Validate crossOriginIsolated and SharedArrayBuffer before enabling shared memory.