vanilla-performance-patterns
Version:
Production-ready performance patterns for vanilla JavaScript. Zero dependencies, maximum performance.
200 lines (198 loc) • 5.38 kB
TypeScript
/**
* @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 };