import EvolutionWorker from './evolution.worker?worker'; import type { Population, Individual } from './evolution'; import type { EvolutionConfig } from './types'; export class WorkerPool { private workers: Worker[] = []; private poolSize: number; constructor(size: number = navigator.hardwareConcurrency || 4) { this.poolSize = size; for (let i = 0; i < size; i++) { this.workers.push(new EvolutionWorker()); } } terminate() { this.workers.forEach(w => w.terminate()); this.workers = []; } async evaluateParallel(population: Population, config: EvolutionConfig): Promise { // Split individuals into chunks const chunkSize = Math.ceil(population.individuals.length / this.poolSize); const chunks: Individual[][] = []; for (let i = 0; i < population.individuals.length; i += chunkSize) { chunks.push(population.individuals.slice(i, i + chunkSize)); } // Dispatch chunks to workers const promises = chunks.map((chunk, index) => { return new Promise((resolve, reject) => { const worker = this.workers[index]; // One-time listener for this request const handler = (e: MessageEvent) => { if (e.data.type === 'EVAL_RESULT') { worker.removeEventListener('message', handler); resolve(e.data.payload); } else if (e.data.type === 'ERROR') { worker.removeEventListener('message', handler); reject(e.data.payload); } }; worker.addEventListener('message', handler); worker.postMessage({ type: 'EVALUATE_ONLY', payload: { individuals: chunk, config } }); }); }); // Wait for all chunks const results = await Promise.all(promises); // Merge results const mergedIndividuals = results.flat(); // Reconstruct population with evaluated individuals return { ...population, individuals: mergedIndividuals }; } }