diff --git a/src/bench.ts b/src/bench.ts index abd2448..6bd0e63 100644 --- a/src/bench.ts +++ b/src/bench.ts @@ -24,9 +24,9 @@ export default class Bench extends EventTarget { _todos: Map = new Map(); - _concurrencyLevel?: 'task' | 'bench'; + concurrency: 'task' | 'bench' | null = null; - _concurrencyLimit = Infinity; + threshold = Infinity; signal?: AbortSignal; @@ -82,7 +82,6 @@ export default class Bench extends EventTarget { * Note: This method does not do any warmup. Call {@link warmup} for that. */ async run() { - console.log('here'); this.dispatchEvent(createBenchEvent('start')); const values: Task[] = []; for (const task of [...this._tasks.values()]) { @@ -93,15 +92,19 @@ export default class Bench extends EventTarget { } /** - * similar to the {@link run} method but runs concurrently rather than sequentially - * default limit is Infinity - */ - async runConcurrently(limit = Infinity, level: typeof this._concurrencyLevel = 'bench') { - this._concurrencyLimit = limit; - this._concurrencyLevel = level; + * Executes tasks concurrently based on the specified concurrency mode. + * + * - When `mode` is set to 'task', each task's iterations run concurrently. + * - When `mode` is set to 'bench', different tasks within the bench run concurrently. + * + * @param threshold - The maximum number of concurrent tasks to run. Defaults to Infinity. + * @param mode - The concurrency mode to determine how tasks are run. Defaults to 'bench'. + */ + async runConcurrently(threshold = Infinity, mode: NonNullable = 'bench') { + this.threshold = threshold; + this.concurrency = mode; - console.log('level', level); - if (level === 'task') { + if (mode === 'task') { return this.run(); } @@ -115,7 +118,7 @@ export default class Bench extends EventTarget { const runningTasks: (Promise | Task)[] = []; // Start tasks up to the concurrency limit - while (runningTasks.length < limit && remainingTasks.length > 0) { + while (runningTasks.length < threshold && remainingTasks.length > 0) { const task = remainingTasks.pop()!; runningTasks.push(this.runTask(task)); } diff --git a/src/task.ts b/src/task.ts index 39d0379..8170611 100644 --- a/src/task.ts +++ b/src/task.ts @@ -52,9 +52,8 @@ export default class Task extends EventTarget { } private async loop(time: number, iterations: number): Promise<{ error?: unknown, samples?: number[] }> { - console.log(this.bench._concurrencyLevel); - const isConcurrent = this.bench._concurrencyLevel === 'task'; - const concurrencyLimit = this.bench._concurrencyLimit; + const concurrent = this.bench.concurrency === 'task'; + const { threshold } = this.bench; let totalTime = 0; // ms const samples: number[] = []; if (this.opts.beforeAll != null) { @@ -96,20 +95,18 @@ export default class Task extends EventTarget { (totalTime < time || ((samples.length + currentTasks.length) < iterations)) && !this.bench.signal?.aborted ) { - console.log('start', samples.length, currentTasks.length, iterations, isConcurrent, currentTasks.length, concurrencyLimit); - if (isConcurrent) { - if (currentTasks.length < concurrencyLimit) { + if (concurrent) { + if (currentTasks.length < threshold) { currentTasks.push(executeTask()); } else { await Promise.all(currentTasks); currentTasks.length = 0; } } else { - // console.log('non concurrent') await executeTask(); } } - // The concurrencyLimit is Infinity + // The threshold is Infinity if (currentTasks.length) { await Promise.all(currentTasks); currentTasks.length = 0; diff --git a/test/index.test.ts b/test/index.test.ts index 5bcee7d..5b42b26 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -154,38 +154,38 @@ test('events order', async () => { expect(abortTask.result).toBeUndefined(); }, 10000); -// test('events order 2', async () => { -// const bench = new Bench({ -// warmupIterations: 0, -// warmupTime: 0, -// }); - -// bench -// .add('foo', async () => { -// await new Promise((resolve) => setTimeout(resolve, 50)); -// }) -// .add('bar', async () => { -// await new Promise((resolve) => setTimeout(resolve, 100)); -// }); - -// const events: string[] = []; - -// const fooTask = bench.getTask('foo')!; -// const barTask = bench.getTask('bar')!; -// fooTask.addEventListener('complete', () => { -// events.push('foo-complete'); -// expect(events).not.toContain('bar-complete'); -// }); - -// barTask.addEventListener('complete', () => { -// events.push('bar-complete'); -// expect(events).toContain('foo-complete'); -// }); - -// await bench.run(); - -// await new Promise((resolve) => setTimeout(resolve, 150)); -// }); +test('events order 2', async () => { + const bench = new Bench({ + warmupIterations: 0, + warmupTime: 0, + }); + + bench + .add('foo', async () => { + await new Promise((resolve) => setTimeout(resolve, 50)); + }) + .add('bar', async () => { + await new Promise((resolve) => setTimeout(resolve, 100)); + }); + + const events: string[] = []; + + const fooTask = bench.getTask('foo')!; + const barTask = bench.getTask('bar')!; + fooTask.addEventListener('complete', () => { + events.push('foo-complete'); + expect(events).not.toContain('bar-complete'); + }); + + barTask.addEventListener('complete', () => { + events.push('bar-complete'); + expect(events).toContain('foo-complete'); + }); + + await bench.run(); + + await new Promise((resolve) => setTimeout(resolve, 150)); +}); test('todo event', async () => { const bench = new Bench({ time: 50 });