UNPKG

vanilla-performance-patterns

Version:

Production-ready performance patterns for vanilla JavaScript. Zero dependencies, maximum performance.

200 lines (198 loc) 5.38 kB
/** * @fileoverview WorkerPool - Dynamic worker pool with auto-scaling * @author - Mario Brosco <mario.brosco@42rows.com> @company 42ROWS Srl - P.IVA: 18017981004 * @module vanilla-performance-patterns/workers * * Pattern inspired by Google Squoosh and Cloudflare Workers * Auto-scales from 2 to N workers based on load * Achieves 5x throughput improvement for CPU-intensive tasks */ interface WorkerPoolOptions { /** Minimum number of workers (default: 2) */ minWorkers?: number; /** Maximum number of workers (default: navigator.hardwareConcurrency) */ maxWorkers?: number; /** Worker script URL or code */ workerScript: string | URL | (() => void); /** Worker type (default: 'classic') */ workerType?: 'classic' | 'module'; /** Idle timeout before worker termination in ms (default: 30000) */ idleTimeout?: number; /** Task timeout in ms (default: 30000) */ taskTimeout?: number; /** Enable shared array buffer if available (default: true) */ enableSharedArrayBuffer?: boolean; /** Task queue limit (default: 1000) */ maxQueueSize?: number; /** Load balancing strategy */ strategy?: 'round-robin' | 'least-loaded' | 'random' | 'sticky'; /** Enable debug logging */ debug?: boolean; } interface Task<T = any, R = any> { id: string; data: T; transferList?: Transferable[]; timeout?: number; priority?: number; resolve: (value: R) => void; reject: (error: Error) => void; startTime?: number; retries?: number; } interface WorkerInfo { worker: Worker; busy: boolean; taskCount: number; totalTasks: number; avgResponseTime: number; lastUsed: number; currentTask?: Task; idleTimer?: number; } interface PoolStats { workers: number; available: number; busy: number; queueLength: number; totalTasks: number; completedTasks: number; failedTasks: number; avgResponseTime: number; throughput: number; } /** * WorkerPool - Production-ready dynamic worker pool * * Features: * - Auto-scaling based on queue pressure * - Multiple load balancing strategies * - Transferable objects support for zero-copy * - SharedArrayBuffer support for shared memory * - Automatic retry with exponential backoff * - Task prioritization and timeout * * @example * ```typescript * // Create pool with inline worker code * const pool = new WorkerPool({ * workerScript: () => { * self.onmessage = (e) => { * const result = expensiveOperation(e.data); * self.postMessage(result); * }; * }, * minWorkers: 2, * maxWorkers: 8 * }); * * // Execute task with transferable * const buffer = new ArrayBuffer(1024); * const result = await pool.execute( * { command: 'process', buffer }, * [buffer] // Transfer ownership * ); * * // Batch execution * const results = await pool.executeMany(tasks); * ``` */ declare class WorkerPool { private options; private workers; private taskQueue; private roundRobinIndex; private isTerminated; private stats; private workerBlobUrl?; constructor(options: WorkerPoolOptions); /** * Initialize minimum number of workers */ private initializeWorkers; /** * Create a new worker */ private createWorker; /** * Handle message from worker */ private handleWorkerMessage; /** * Handle worker error */ private handleWorkerError; /** * Restart a crashed worker */ private restartWorker; /** * Schedule idle timeout for worker */ private scheduleIdleTimeout; /** * Terminate an idle worker */ private terminateWorker; /** * Get next available worker based on strategy */ private getAvailableWorker; /** * Process task queue */ private processQueue; /** * Execute task on specific worker */ private executeOnWorker; /** * Generate unique ID */ private generateId; /** * Execute a task on the pool */ execute<T = any, R = any>(data: T, transferList?: Transferable[], options?: { timeout?: number; priority?: number; }): Promise<R>; /** * Execute multiple tasks in parallel */ executeMany<T = any, R = any>(tasks: Array<{ data: T; transferList?: Transferable[]; options?: { timeout?: number; priority?: number; }; }>): Promise<R[]>; /** * Execute tasks with map function */ map<T = any, R = any>(items: T[], mapper: (item: T) => any, options?: { concurrency?: number; timeout?: number; transferList?: (item: T) => Transferable[]; }): Promise<R[]>; /** * Get pool statistics */ getStats(): PoolStats; /** * Set pool size */ setPoolSize(min: number, max: number): void; /** * Terminate all workers and clean up */ terminate(): Promise<void>; } /** * Create a simple worker pool for function execution */ declare function createFunctionWorkerPool<T = any, R = any>(fn: (data: T) => R | Promise<R>, options?: Omit<WorkerPoolOptions, 'workerScript'>): WorkerPool; export { WorkerPool, createFunctionWorkerPool }; export type { Task, WorkerInfo, WorkerPoolOptions, PoolStats as WorkerPoolStats };