npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nadrif/thread

v0.1.1

Published

Enterprise Web Worker & GPU Compute framework — cross-platform thread pools, work-stealing, WebGPU shaders, with framework adapters for Preact/React/Svelte/Vue/Solid and state managers Zustand/Redux/Jotai/MobX/Signals.

Readme

thread

Enterprise Web Worker & GPU Compute Framework

A modular, feature-rich library for running CPU-intensive work in Web Workers and WebGPU compute shaders. Includes a thread pool with work-stealing, dependency tracking, health checks, 57+ built-in GPU operations, and framework adapters for Preact, React, Svelte, Vue, Solid, Zustand, Redux, and Preact Signals.


Table of Contents


Installation

npm install @nadrif/thread
# or
bun add @nadrif/thread

Peer dependency (optional — only needed for hooks):

npm install preact   # or react

Quick Start

CPU Workers

import { createThread, createPool } from 'thread';

// Single thread — run a function in a Web Worker
const t = createThread((x) => x * 2);
console.log(await t.run(5)); // 10

// Thread pool — distribute work across 4 workers
const pool = createPool(4, (x) => x + 1);
const { id, promise } = pool.run(1);
console.log(await promise); // 2

GPU Compute

import { createGPUOp } from 'thread';

// Define a GPU operation from a plain JS function
const gpu = createGPUOp('double', (data) => data.value * 2);

const result = await gpu.run('double', {
  inputs: { data: new Float32Array([1, 2, 3]) },
  outputs: { result: 3 },
});
console.log(result.result); // Float32Array [2, 4, 6]

Environment Compatibility

thread works across 5+ JavaScript runtimes out of the box. The library auto-detects your environment and uses the appropriate APIs for Workers, GPU, and config loading.

Supported Runtimes

| Runtime | Worker API | GPU API | Config Loading | Import Path | |---------|-----------|---------|---------------|-------------| | Browser | Web Workers (Blob URLs) | navigator.gpu | Filesystem (Node) or programmatic | thread | | Node.js | worker_threads (eval) | @aspect-build/webgpu-node | fs.readFileSync | thread/node | | Bun | worker_threads (eval) | bun-webgpu (Dawn FFI) or Bun.gpu | fs.readFileSync | thread/node | | Deno | Deno Workers (Blob URLs) | Deno.gpu | Deno.readTextFileSync | thread/deno | | Edge | Web Workers (Blob URLs) | navigator.gpu | Programmatic only | thread/edge | | Cloudflare Workers | No Worker support | navigator.gpu | Programmatic only | thread/edge |

Environment-Specific Entry Points

Use the appropriate import for your runtime:

// Browser (auto-detected)
import { Thread, ThreadPool } from 'thread';

// Node.js / Bun
import { Thread, ThreadPool } from 'thread/node';

// Deno
import { Thread, ThreadPool } from 'thread/deno';

// Edge (Cloudflare Workers, Vercel Edge, Netlify Edge)
import { Thread, ThreadPool } from 'thread/edge';

The main thread export uses conditional exports — your bundler/runtime automatically picks the right entry point based on the browser, node, bun, deno, and edge conditions.

Environment Detection

Use the env object to detect your runtime and available features:

import { env } from 'thread/env';

console.log(env.runtime);      // 'browser' | 'node' | 'bun' | 'deno' | 'edge'
console.log(env.isNode);       // true
console.log(env.hasWorker);    // true
console.log(env.hasGPU);       // false (unless WebGPU is enabled)
console.log(env.hasFS);        // true (Node/Bun only)
console.log(env.isMainThread); // true

// Platform-specific helpers
const cwd = env.getCwd();                    // '/home/user/project'
const fs = env.requireModule('node:fs');     // fs module or null
const exists = env.fileExists('./config.js'); // true/false
const path = env.resolvePath('src', 'index.js'); // '/home/user/project/src/index.js'

Config in Different Environments

Browser/Edge: Config must be set programmatically (no filesystem access):

import { setProgrammaticConfig } from 'thread/config';

setProgrammaticConfig({
  framework: 'react',
  stateManager: 'zustand',
  gpu: { workgroupSize: 512 },
});

Node.js/Bun/Deno: Use the standard thread.config.js file in your project root:

// thread.config.js
import { defineConfig } from 'thread/config';

export default defineConfig({
  framework: 'preact',
  stateManager: 'zustand',
});

GPU in Different Environments

WebGPU availability varies by runtime:

import { isGPUAvailable, gpuEnv } from 'thread/gpu/env';

// Async check (recommended)
if (await isGPUAvailable()) {
  const gpu = new GPUCompute({ shader: myShader });
  await gpu.init();
} else {
  // Fall back to CPU
  const cpu = createGPUWithFallback(shader, cpuFn);
}

// Operations defined with a JS function auto-fallback to CPU when GPU
// dispatch fails (e.g. adapter found but shader execution unsupported).
gpu.define('double', (data) => data.value * 2);
const result = await gpu.run('double', { inputs: { data } }); // works either way

// Sync check (fast, less reliable)
if (gpuEnv.sync) {
  console.log('WebGPU detected');
}

// Detailed diagnostics
const info = await gpuEnv.info();
console.log(info);
// { available: true, runtime: 'browser', adapterName: 'NVIDIA RTX 4090', ... }

Node.js GPU: Install a WebGPU binding:

npm install @aspect-build/webgpu-node
# or
npm install node-webgpu

Bun GPU: Install bun-webgpu (Dawn FFI bindings):

bun add bun-webgpu

The library auto-detects bun-webgpu and calls setupGlobals() to expose navigator.gpu. You can also call it eagerly for sync detection:

import { setupGlobals } from 'bun-webgpu';
setupGlobals();

GPU fallback: When a GPU adapter is detected but shader dispatch fails (e.g. missing DXC/Dawn binaries), operations defined with a JS function automatically fall back to the CPU path. No manual fallback code needed.


Configuration

thread uses a config file (thread.config.js) in your project root to configure the library globally. All fields are optional — thread works out of the box with sensible defaults (Preact + Zustand).

Config File Format

// thread.config.js
import { defineConfig } from 'thread/config';

export default defineConfig({
  // UI framework — hooks are auto-resolved at load time
  framework: 'react',        // 'preact' | 'react' | 'svelte' | 'vue' | 'solid' | 'angular' | 'custom'

  // State manager — determines which adapter shortcuts are available
  stateManager: 'zustand',   // 'zustand' | 'signals' | 'redux' | 'jotai' | 'mobx' | 'vanilla' | 'custom'

  // GPU compute defaults (applied to all GPUCompute instances)
  gpu: {
    workgroupSize: 256,             // Must match @workgroup_size(N) in shaders
    maxBufferSize: 256 * 1024 * 1024, // 256 MB max buffer
    powerPreference: 'high-performance', // 'low-power' | 'high-performance'
    bunWebgpu: true,                // Auto-import bun-webgpu in Bun (if installed)
    fallbackAdapter: true,          // Request software adapter if no GPU found
    // cpuFallback: (input) => { ... },  // Called when WebGPU unavailable
  },

  // Thread defaults (applied to all threads via factories)
  thread: {
    timeout: 30_000,                // 30 second task timeout
    // idleTimeout: 60_000,         // Auto-terminate idle threads
    // healthCheckInterval: 10_000, // Ping threads every 10s
  },

  // Pool defaults (applied to all pools via factories)
  pool: {
    autoRestart: true,              // Replace crashed workers
    enableStealing: true,           // Work-stealing between threads
    // maxSize: 16,                 // Cap thread count
  },

  // Development options
  dev: {
    log: false,                     // Forward worker logs to main thread
    metrics: false,                 // Enable metrics collection
    warnOnLongTask: 0,              // Warn if task > N ms (0 = disabled)
  },
});

Supported Frameworks

| Framework | Import path | Hook support | Notes | |-----------|------------|-------------|-------| | Preact | preact/hooks | Full | Default. Identical API to React. | | React | react | Full | Works with React 18+. | | Svelte | svelte/reactivity | Partial | Svelte 5 runes. Some hooks are shims. | | Vue | vue | Partial | Composition API. ref()useState. | | Solid | solid-js | Full | Exports hooks directly. | | Angular | — | — | Coming soon. Use custom with a shim. | | Custom | — | — | User provides customHookSource. |

Supported State Managers

| State Manager | Adapter type | Thread adapter | GPU adapter | Notes | |--------------|-------------|---------------|-------------|-------| | Zustand | action | createZustandBinder | createGPUBinder | Default. Action-based. | | Signals | signal | createSignalBinder | createGPUSignalBinder | Preact Signals. .value based. | | Redux | setter | createStoreBinder | createGPUStoreBinder | Generic setter callback. | | Jotai | setter | createStoreBinder | createGPUStoreBinder | Uses Redux adapter. | | MobX | setter | createStoreBinder | createGPUStoreBinder | Uses Redux adapter. | | Vanilla | setter | createStoreBinder | createGPUStoreBinder | Any setter function. | | Custom | — | — | — | User provides customAdapter. |

Custom Framework / State Manager

// thread.config.js
import { defineConfig } from 'thread/config';

export default defineConfig({
  framework: 'custom',
  customHookSource: async () => {
    // Import your framework's hooks
    const mod = await import('my-framework/hooks');
    return {
      useState: mod.useState,
      useEffect: mod.useEffect,
      useRef: mod.useRef,
      useCallback: mod.useCallback,
      useMemo: mod.useMemo,
    };
  },

  stateManager: 'custom',
  customAdapter: (instance, store, action) => ({
    run: async (...args) => {
      const result = await instance.run(...args);
      store.dispatch({ type: action, payload: result });
    },
    destroy: () => {},
  }),
});

Architecture

thread/
├── package.json
├── README.md
├── thread.config.js.example    Example config file
├── src/
│   ├── index.js              Main barrel export (re-exports everything)
│   ├── config.js             Config entry (thread/config)
│   ├── types.js              TypeScript type definitions
│   ├── thread.js             Thread class — single worker lifecycle
│   ├── pool.js               ThreadPool — priority queue, deps, work-stealing
│   ├── metrix.js             Metrics — performance counters
│   ├── serializer.js         Serializer — JSON-safe with function support
│   ├── error.js              Error hierarchy (ThreadError, GPUComputeError, …)
│   ├── factory.js            Factory functions (createThread, createPool, …)
│   ├── hooks.js              Framework-agnostic hooks (useThread, usePool, …)
│   ├── adapters.js           Framework adapters (Zustand, Signals, …)
│   ├── config/
│   │   ├── index.js          Config loader (getConfig, setConfig)
│   │   ├── define.js         defineConfig() helper
│   │   ├── schema.js         Defaults, validation, mergeWithDefaults
│   │   ├── frameworks.js     Framework → hooks resolver
│   │   └── adapters.js       State manager → adapter registry
│   └── gpu/
│       ├── index.js          GPU barrel export
│       ├── gpu.js            GPUCompute class — WebGPU executor
│       ├── shaders.js        Built-in ops, shader DSL (57+ ops)
│       ├── helpers.js        Auto-boxing, transpile, jsToWgsl
│       ├── chains.js         PipelineChain + DataPipelineChain
│       ├── special.js        Multi-pass: matmul, reduce, histogram, scan
│       ├── hooks.js          GPU-specific hooks (useGPU, useGPURun, …)
│       └── adapters.js       GPU-specific adapters (Zustand, Signals, …)
└── tests/
    └── thread.spec.js        Full test suite (238 tests, 759 expects)

CPU Workers

Single Thread

Run a function in a dedicated Web Worker. The thread is created lazily on the first run() call and can be terminated when no longer needed.

import { createThread } from 'thread';

// Simple function — auto-serialized and sent to a worker
const t = createThread((a, b) => a + b);
console.log(await t.run(3, 4)); // 7

// With options
const t2 = createThread((data) => process(data), {
  timeout: 10_000,          // reject if task takes >10s
  idleTimeout: 60_000,      // auto-terminate after 60s idle
  concurrency: 2,           // allow 2 concurrent tasks
  onLog: (msg) => console.log('[worker]', msg),
  onTiming: (ms) => console.log(`Done in ${ms.toFixed(1)}ms`),
});

// Cleanup
await t.terminate();

Thread Pool

Distribute work across multiple workers with a priority queue, dependency tracking, and work-stealing.

import { createPool } from 'thread';

const pool = createPool(4, (n) => {
  let sum = 0;
  for (let i = 0; i < n; i++) sum += Math.sqrt(i);
  return sum;
});

// Run 20 tasks across 4 workers
const results = await Promise.all(
  Array.from({ length: 20 }, (_, i) => pool.run(1_000_000 + i).promise)
);

// Priority queue — lower number = higher priority
pool.run(urgentData, { priority: 0 });
pool.run(batchData,  { priority: 10 });

// Dependencies — chain tasks
const step1 = pool.run('raw-data');
const step2 = pool.run(step1.id, { dependsOn: [step1.id] });
await step2.promise;

// Dynamic resizing
pool.scaleTo(8);   // burst mode
await pool.drain();
pool.scaleTo(2);   // back to normal

Stateful Workers

Workers with persistent state across tasks (setup → exec → cleanup):

import { createThread } from 'thread';

const db = createThread({
  setup() {
    return { conn: openDatabase(), cache: new Map() };
  },
  async exec(state, query, ctx) {
    ctx.log(`Running: ${query}`);
    ctx.reportProgress(0);
    if (state.cache.has(query)) return state.cache.get(query);
    const result = await state.conn.query(query);
    state.cache.set(query, result);
    ctx.reportProgress(1);
    return result;
  },
  async cleanup(state) {
    await state.conn.close();
  },
}, { timeout: 10_000 });

const rows = await db.run('SELECT * FROM users');
await db.terminateGracefully(); // cleanup runs automatically

Streaming

Process large arrays in chunks, yielding results as they complete:

const t = createThread((chunk) => chunk.map((x) => x * x));
const data = Array.from({ length: 10_000 }, (_, i) => i);

// Process in chunks of 1000
for (let i = 0; i < data.length; i += 1000) {
  const chunk = data.slice(i, i + 1000);
  const result = await t.run(chunk);
  console.log(`Chunk ${i / 1000 + 1} done:`, result);
}

Function Chaining

Chain multiple operations on the same thread:

const t = createThread((x) => x * 2);

const chain = t.runChain(5);       // start with 5
chain.run((x) => x + 1);          // → 11
chain.run((x) => x * 3);          // → 33
const final = await chain.run((x) => x - 1); // → 32

GPU Compute

One-Liner Ops

Define GPU operations from plain JavaScript functions. The function is automatically transpiled to WGSL and executed on the GPU:

import { createGPUOp } from 'thread';

const gpu = createGPUOp('double', (data) => data.value * 2);

const result = await gpu.run('double', {
  inputs: { data: new Float32Array([1, 2, 3, 4]) },
  outputs: { result: 4 },
});
console.log(result.result); // Float32Array [2, 4, 6, 8]

Multi-Op Pipelines

Register multiple operations and switch between them:

import { createGPUPipeline } from 'thread';

const gpu = createGPUPipeline([
  ['double', (data) => data.value * 2],
  ['negate', (data) => -data.value],
  ['sqrt',   (data) => Math.sqrt(data.value)],
]);

// Run any registered op
await gpu.run('double', { inputs: { data }, outputs: { result: 4 } });
await gpu.run('sqrt',   { inputs: { data }, outputs: { result: 4 } });

Built-in Operations

57+ built-in operations — zero shader code required:

import { GPUCompute } from 'thread';

const gpu = new GPUCompute();

// Arithmetic
await gpu.run('multiply', { inputs: { a, b }, outputs: { result: N } });
await gpu.run('add',      { inputs: { a, b }, outputs: { result: N } });
await gpu.run('subtract', { inputs: { a, b }, outputs: { result: N } });
await gpu.run('divide',   { inputs: { a, b }, outputs: { result: N } });
await gpu.run('power',    { inputs: { a, b }, outputs: { result: N } });

// Math
await gpu.run('sqrt',  { inputs: { data }, outputs: { result: N } });
await gpu.run('abs',   { inputs: { data }, outputs: { result: N } });
await gpu.run('sin',   { inputs: { data }, outputs: { result: N } });
await gpu.run('exp',   { inputs: { data }, outputs: { result: N } });
await gpu.run('log',   { inputs: { data }, outputs: { result: N } });

// Comparison
await gpu.run('clamp', { inputs: { data }, uniforms: { min, max }, outputs: { result: N } });
await gpu.run('lerp',  { inputs: { a, b }, uniforms: { t }, outputs: { result: N } });

// Aggregation
await gpu.run('reduce_sum', { inputs: { data }, outputs: { result: N } });
await gpu.run('reduce_max', { inputs: { data }, outputs: { result: N } });
await gpu.run('reduce_min', { inputs: { data }, outputs: { result: N } });

// Matrix
await gpu.run('matmul', { inputs: { A, B }, uniforms: { M, N, K }, outputs: { C } });

Pipeline Chaining

Chain multiple GPU operations without copying data back to the CPU:

const gpu = new GPUCompute();
gpu.define('scale', (data, { factor }) => data.value * factor);
gpu.define('offset', (data, { bias }) => data.value + bias);

const chain = gpu.pipe('scale', 4)
  .run({ data: new Float32Array([1, 2, 3, 4]) }, { factor: new Float32Array([2]) })
  .pipe('offset', 4)
  .run({}, { bias: new Float32Array([10]) });

const result = await chain.result();
// [12, 14, 16, 18]

Fluent Data Pipelines

Use named methods for a fluent API:

const gpu = new GPUCompute();
gpu.define('normalize', (data, { mean, std }) => (data.value - mean) / std);
gpu.define('clamp', (data, { min, max }) => Math.min(Math.max(data.value, min), max));

const pipeline = gpu.pipe('normalize', 1000)
  .normalize({ mean: new Float32Array([50]), std: new Float32Array([15]) })
  .clamp({ min: new Float32Array([0]), max: new Float32Array([100]) })
  .result();

const normalized = await pipeline;

Map (Parallel Transform)

Apply a function to every element in parallel:

const gpu = new GPUCompute();
const data = new Float32Array(1_000_000);

// Parallel map — runs on GPU
const result = await gpu.map(data, (x) => x * x + 1);

Reductions

Sum, min, max across large datasets:

import { createGPUReducer } from 'thread';

const gpu = createGPUReducer();
const data = new Float32Array(1_000_000);

const sum = await gpu.run('reduce_sum', { inputs: { data }, outputs: { result: 1 } });
const max = await gpu.run('reduce_max', { inputs: { data }, outputs: { result: 1 } });
const min = await gpu.run('reduce_min', { inputs: { data }, outputs: { result: 1 } });

console.log(`Sum: ${sum.result[0]}, Min: ${min.result[0]}, Max: ${max.result[0]}`);

Profiling & Auto-Tuning

Measure GPU performance and auto-tune workgroup size:

const gpu = new GPUCompute();

// Profile a single op
const profile = await gpu.profile('multiply', {
  inputs: { a: new Float32Array(1024), b: new Float32Array(1024) },
  outputs: { result: 1024 },
});
console.log(profile); // { avg: 0.12, min: 0.11, max: 0.15, ... }

// Auto-tune workgroup size
const optimal = await gpu.autoTune('multiply', {
  inputs: { a: new Float32Array(1024), b: new Float32Array(1024) },
  outputs: { result: 1024 },
});
console.log(`Optimal workgroup size: ${optimal.workgroupSize}`);

Framework Integration

Hooks

Lifecycle-bound hooks for Preact/React. The framework is resolved automatically from your thread.config.js:

import { useThread, usePool, useGPU } from 'thread';

// Thread hook — auto-creates and auto-destroys a thread
function DataProcessor({ data }) {
  const { run, loading, error, result } = useThread(
    (items) => items.map((x) => x * 2),
    { timeout: 10_000 }
  );

  return (
    <div>
      {loading && <Spinner />}
      {error && <Error message={error} />}
      {result && <Results data={result} />}
      <button onClick={() => run(data)} disabled={loading}>Process</button>
    </div>
  );
}

// Pool hook — metrics update automatically
function ParallelWorker({ items }) {
  const { run, status, metrics } = usePool(4, (item) => process(item));

  return (
    <div>
      <button onClick={() => items.forEach((item) => run(item))}>Process all</button>
      <p>{status().busy} threads busy</p>
      <p>Avg: {metrics.avg?.toFixed(1)}ms</p>
    </div>
  );
}

// GPU hook — reactive GPU state
function GPUDashboard() {
  const { run, result, loading, status } = useGPU();

  return (
    <div>
      <p>GPU: {status}</p>
      <button onClick={() => run('multiply', data1, data2)} disabled={loading}>
        {loading ? 'Computing...' : 'Run GPU'}
      </button>
      {result && <pre>{JSON.stringify(Array.from(result))}</pre>}
    </div>
  );
}

Adapters

Bind threads/GPUs to your state manager. Results flow automatically:

import { create } from 'zustand';
import { createThread, createZustandBinder } from 'thread';

// Zustand store
const useStore = create((set) => ({
  data: null,
  error: null,
  setData: (data) => set({ data, error: null }),
  setError: (error) => set({ error }),
}));

// Thread + adapter
const thread = createThread((query) => db.query(query));
const binder = createZustandBinder(thread, useStore, 'setData', {
  errorAction: 'setError',
});

// Every run() result flows to the store
await binder.run('SELECT * FROM users');
// → useStore.getState().data is now the result

Error Handling

import {
  ThreadError,
  ThreadTimeoutError,
  ThreadAbortError,
  ThreadTerminatedError,
  ThreadHealthError,
  ThreadDependencyError,
  GPUComputeError,
} from 'thread';

try {
  await thread.run(data);
} catch (err) {
  if (err instanceof ThreadTimeoutError) {
    console.error('Task timed out');
  } else if (err instanceof ThreadAbortError) {
    console.error('Task was aborted');
  } else if (err instanceof GPUComputeError) {
    console.error('GPU failed:', err.message);
  } else {
    throw err; // re-throw non-thread errors
  }
}

| Error | When | |--------------------------|-------------------------------------------| | ThreadTimeoutError | Task exceeded its timeout | | ThreadAbortError | Task was aborted via AbortController | | ThreadTerminatedError | Thread/pool was terminated | | ThreadHealthError | Health check failed (internal) | | ThreadDependencyError | A dependency task failed | | GPUComputeError | Shader compilation, buffer, or dispatch |


TypeScript

import type {
  // Thread & Pool
  ThreadDefinition,
  ThreadOptions,
  ThreadRunOptions,
  PoolOptions,
  PoolRunOptions,
  PoolTaskResult,
  PoolStatus,
  // GPU
  GPUComputeOptions,
  GPUComputeInput,
  GPUComputeSnapshot,
  OpDeclaration,
  // Hooks
  UseThreadReturn,
  UsePoolReturn,
  UseGPUReturn,
  UseGPURunReturn,
  // Adapters
  ZustandBinderOptions,
  SignalBinderOptions,
  StoreBinderOptions,
  BinderHandle,
  Signal,
  // Common
  MetricsSnapshot,
  ThreadEventName,
  // Config
  threadConfig,
  threadGPUConfig,
  threadThreadConfig,
  threadPoolConfig,
  threadDevConfig,
} from 'thread/types';

Examples

18 runnable examples covering every feature — run them with bun run examples/<file>.

Basic (01-06)

| Example | File | Description | |---------|------|-------------| | Basic Thread | 01-basic-thread.js | Single worker, function definition, error handling | | Thread Pool | 02-thread-pool.js | Multi-worker pool with priorities and scaling | | Stateful Worker | 03-stateful-worker.js | Worker with persistent state (setup/exec/cleanup) | | Serializer | 04-serializer.js | JSON-safe serialization with function support | | Error Handling | 05-error-handling.js | Error hierarchy, catch patterns, abort/cancel | | Metrics | 06-metrics.js | Performance counters, throughput, error rates |

Advanced (07-12)

| Example | File | Description | |---------|------|-------------| | Streaming | 07-streaming.js | Chunked processing with AbortController | | Function Chain | 08-function-chain.js | Chain multiple ops on same thread | | Hot-Swap & Events | 09-hot-swap-events.js | Replace worker function at runtime, event subscriptions | | Pool Pipeline | 10-pool-pipeline.js | Chain pool tasks with dependency tracking | | Dynamic Pool | 11-dynamic-pool.js | Scale pool up/down, drain, work stealing | | Managed Worker | 12-managed-worker.js | Auto-logging, metrics, health checks |

GPU Compute (13-18)

| Example | File | Description | |---------|------|-------------| | GPU Basics | 13-gpu-compute-basics.js | define, run, map, inspect — all with CPU fallback | | Custom Ops | 14-gpu-custom-ops.js | Uniforms, multi-input, index-aware ops | | Pipeline Chains | 15-gpu-pipeline-chains.js | pipe(), PipelineChain, DataPipelineChain | | Special Ops | 16-gpu-special-ops.js | reduce, scan, histogram, argmax, matmul | | Batch & Profile | 17-gpu-batch-profile.js | runBatch, profile, runMany | | Fallback Workflow | 18-gpu-fallback-workflow.js | isGPUAvailable, createGPUWithFallback, helpers |


Real-Life Use Cases

1. Financial Data Processing (Real-time EMA)

Compute Exponential Moving Averages on streaming price data using the GPU. Processing 1M price ticks that would take seconds on CPU completes in milliseconds on GPU:

import { createGPUOp } from 'thread';

const gpu = createGPUOp('ema', (data, { alpha }) =>
  data.value * alpha + data.index * (1 - alpha)
);

// Process 1M price ticks in parallel
const prices = new Float32Array(priceTicks);
const ema = await gpu.run('ema', {
  inputs:   { data: prices },
  uniforms: { alpha: new Float32Array([0.1]) },
  outputs:  { result: prices.length },
});

2. Image Processing Pipeline

Process image pixels through a chain of filters without copying data back to the CPU between steps:

import { GPUCompute } from 'thread';

const gpu = new GPUCompute();
gpu.define('grayscale', (data) => data.value * 0.299 + data.value * 0.587 + data.value * 0.114);
gpu.define('contrast', (data, { factor }) => (data.value - 0.5) * factor + 0.5);
gpu.define('clamp01', (data) => Math.min(Math.max(data.value, 0), 1));

const output = await gpu.pipe(pixelData)
  .grayscale()
  .contrast({ factor: new Float32Array([1.2]) })
  .clamp01()
  .result();

3. Scientific Computing — Matrix Multiply

Multiply two matrices on the GPU. The built-in matmul op handles the tiling and parallel reduction automatically:

import { GPUCompute } from 'thread';

const gpu = new GPUCompute();
const A = new Float32Array([1, 2, 3, 4, 5, 6]); // 2x3
const B = new Float32Array([7, 8, 9, 10, 11, 12]); // 3x2

const result = await gpu.run('matmul', {
  inputs:   { A, B },
  uniforms: {
    M: new Float32Array([2]),
    N: new Float32Array([2]),
    K: new Float32Array([3]),
  },
  outputs: { C: 4 },
});
// C = [58, 64, 139, 154]

4. Data Analytics — Histogram & Statistics

Build a histogram and find extremes in sensor data. Three GPU passes process millions of data points in parallel:

import { createGPUReducer } from 'thread';

const gpu = createGPUReducer();
const sensorData = new Float32Array(sensorReadings);

// Find min, max, sum in parallel
const sum = await gpu.run('reduce_sum', { inputs: { data: sensorData }, outputs: { result: sensorData.length } });
const max = await gpu.run('reduce_max', { inputs: { data: sensorData }, outputs: { result: sensorData.length } });
const min = await gpu.run('reduce_min', { inputs: { data: sensorData }, outputs: { result: sensorData.length } });

const mean = sum.result[0] / sensorData.length;

5. Parallel File Processing (Thread Pool)

Process thousands of files across multiple workers. The pool automatically distributes work and handles failures:

import { createPool } from 'thread';

const pool = createPool(8, async (filePath) => {
  const text = await fetch(filePath).then(r => r.text());
  return { path: filePath, wordCount: text.split(/\s+/).length };
});

const files = await glob('**/*.md');
const results = await Promise.all(
  files.map(f => pool.run(f).promise)
);

console.log(`Processed ${results.length} files`);

6. Real-Time Dashboard (React + Zustand)

Bind GPU compute results to a Zustand store for reactive UI updates. The adapter handles the bridge between GPU and React state:

import { create } from 'zustand';
import { createGPUOp, createGPUBinder } from 'thread';

const useStore = create((set) => ({
  metrics: null,
  setMetrics: (data) => set({ metrics: data }),
}));

const gpu = createGPUOp('normalize', (data, { mean, std }) =>
  (data.value - mean) / std
);

const binder = createGPUBinder(gpu, useStore, 'setMetrics');

// In a component — click triggers GPU compute, result flows to store
function Dashboard() {
  const metrics = useStore(s => s.metrics);
  return (
    <div>
      <button onClick={() => binder.run('normalize', { inputs: { data: rawData }, ... })}>
        Normalize
      </button>
      {metrics && <pre>{JSON.stringify(metrics)}</pre>}
    </div>
  );
}

7. WebGPU + CPU Fallback (Universal)

Gracefully fall back to CPU when WebGPU is unavailable. Works on any device — GPU if available, CPU otherwise:

import { createGPUWithFallback } from 'thread';

const gpu = createGPUWithFallback(
  `@compute @workgroup_size(256) fn main(...) { ... }`,
  (input) => {
    // CPU fallback — same logic, slower
    const { data } = input.inputs;
    const result = new Float32Array(data.length);
    for (let i = 0; i < data.length; i++) result[i] = data[i] * 2;
    return { result };
  }
);

// Works on any device — GPU if available, CPU otherwise
const result = await gpu.computeWithFallback({
  inputs: { data: new Float32Array([1, 2, 3]) },
  outputBuffers: { result: 3 },
});

8. Search Engine — Parallel Indexing (React + Pool)

Build a search index by processing documents in parallel across a thread pool, with real-time progress in the UI:

import { createPool, usePool, usePoolMetrics } from 'thread';

// Create pool outside component (shared across renders)
const indexPool = createPool(4, async (doc) => {
  const tokens = tokenize(doc.content);
  const embeddings = await computeEmbeddings(tokens);
  return { id: doc.id, tokens, embeddings };
});

function SearchIndexer({ documents }) {
  const { run, status } = usePool(indexPool);
  const metrics = usePoolMetrics(indexPool, 500);

  const handleIndex = () => {
    documents.forEach((doc) => run(doc));
  };

  return (
    <div>
      <button onClick={handleIndex}>Index {documents.length} docs</button>
      <p>{status().busy}/{status().total} workers busy</p>
      <p>{metrics.count}/{documents.length} indexed</p>
      <p>{metrics.throughput?.toFixed(0)} docs/sec</p>
    </div>
  );
}

API Reference

Classes

| Class | Description | |-------|-------------| | Thread | Single Web Worker with full lifecycle | | ThreadPool | Worker pool with priorities, deps, work-stealing | | GPUCompute | WebGPU compute shader executor | | PipelineChain | Fluent multi-step GPU pipeline | | DataPipelineChain | Data-carrying pipeline with named methods | | Metrics | Performance counter (avg, throughput, errors) | | Serializer | JSON-safe serialization with function support |

Factories

| Function | Description | |----------|-------------| | createThread(def, opts) | Create a validated thread | | createPool(size, def, opts) | Create a validated pool | | createWorker(fn, opts) | One-liner thread with error logging | | createWorkerDef(def) | Reusable worker definition | | createManagedThread(def, opts) | Thread with auto logging, metrics, health | | createGPUCompute(opts) | Create a GPU instance | | createGPUOp(name, fn, opts) | GPU with a single JS-defined op | | createGPUPipeline(ops, opts) | GPU with multiple pre-registered ops | | createGPUReducer(opts) | GPU ready for reductions | | createGPUWithFallback(shader, fn, opts) | GPU with CPU fallback |

Hooks

| Hook | Description | |------|-------------| | useThread(def, opts) | Lifecycle-bound thread with reactive state | | usePool(size, def, opts) | Lifecycle-bound pool with metrics | | useThreadMetrics(thread, ms) | Poll thread metrics | | usePoolMetrics(pool, ms) | Poll pool metrics | | useThreadWorker(thread) | Stable run for external thread | | useThreadEvent(thread, event, handler) | Subscribe to thread events | | useGPU(opts) | Lifecycle-bound GPU with reactive state | | useGPURun(gpu) | Stable run for external GPU | | useGPUMetrics(gpu, ms) | Poll GPU metrics | | useGPUStatus(gpu, ms) | Reactive GPU status string |

Adapters

| Function | Description | |----------|-------------| | createZustandBinder(thread, store, action, opts) | Bind thread → Zustand | | createSignalBinder(thread, signal, opts) | Bind thread → Signal | | createStoreBinder(thread, setter, opts) | Bind thread → any setter | | createPoolBinder(pool, setter, opts) | Bind pool → any setter | | createGPUBinder(gpu, store, action, opts) | Bind GPU → Zustand | | createGPUSignalBinder(gpu, signal, opts) | Bind GPU → Signal | | createGPUStoreBinder(gpu, setter, opts) | Bind GPU → any setter |

Config

| Function | Description | |----------|-------------| | defineConfig(config) | Create a validated, frozen config object | | getConfig() | Get the resolved config (cached) | | setConfig() | Clear caches and force re-resolution |

Errors

| Error | When | |-------|------| | ThreadError | Base class for all threads errors | | ThreadTimeoutError | Task exceeded its timeout | | ThreadAbortError | Task was aborted | | ThreadTerminatedError | Thread/pool was terminated | | ThreadHealthError | Health check failed | | ThreadDependencyError | A dependency task failed | | GPUComputeError | GPU shader, buffer, or dispatch failure |


License

MIT — Nadrif LLC