From 08f3f44cef6256fdbab1a2a56842b291fd6dcd42 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 5 May 2023 20:41:43 +0200 Subject: [PATCH] feat: add custom worker weights to worker choice strategies options MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- CHANGELOG.md | 1 + src/pools/abstract-pool.ts | 3 + src/pools/cluster/dynamic.ts | 5 + src/pools/cluster/fixed.ts | 5 + src/pools/pool.ts | 4 + .../abstract-worker-choice-strategy.ts | 13 +- .../fair-share-worker-choice-strategy.ts | 36 ++- .../less-busy-worker-choice-strategy.ts | 6 +- .../less-used-worker-choice-strategy.ts | 6 +- .../selection-strategies-types.ts | 7 + ...hted-round-robin-worker-choice-strategy.ts | 74 +----- src/pools/thread/dynamic.ts | 5 + src/pools/thread/fixed.ts | 5 + .../selection-strategies.test.js | 212 +++++++++--------- ...round-robin-worker-choice-strategy.test.js | 18 +- .../worker-choice-strategy-context.test.js | 50 ----- 16 files changed, 191 insertions(+), 259 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ebe01c..c2a0b95f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support multiple task functions per worker. +- Add custom worker weights support to worker choice strategies options. ### Changed diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index edf2b29a..71067f5c 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -180,6 +180,9 @@ export abstract class AbstractPool< /** @inheritDoc */ public abstract get type (): PoolType + /** @inheritDoc */ + public abstract get size (): number + /** * Number of tasks running in the pool. */ diff --git a/src/pools/cluster/dynamic.ts b/src/pools/cluster/dynamic.ts index c42e02b0..eb2b9965 100644 --- a/src/pools/cluster/dynamic.ts +++ b/src/pools/cluster/dynamic.ts @@ -39,6 +39,11 @@ export class DynamicClusterPool< return PoolType.DYNAMIC } + /** @inheritDoc */ + public get size (): number { + return this.max + } + /** @inheritDoc */ protected get full (): boolean { return this.workerNodes.length === this.max diff --git a/src/pools/cluster/fixed.ts b/src/pools/cluster/fixed.ts index ed4f6fed..10ee92c5 100644 --- a/src/pools/cluster/fixed.ts +++ b/src/pools/cluster/fixed.ts @@ -100,6 +100,11 @@ export class FixedClusterPool< return PoolType.FIXED } + /** @inheritDoc */ + public get size (): number { + return this.numberOfWorkers + } + /** @inheritDoc */ protected get full (): boolean { return this.workerNodes.length === this.numberOfWorkers diff --git a/src/pools/pool.ts b/src/pools/pool.ts index 992aaaf1..49123f54 100644 --- a/src/pools/pool.ts +++ b/src/pools/pool.ts @@ -127,6 +127,10 @@ export interface IPool< * If it is `'dynamic'`, it provides the `max` property. */ readonly type: PoolType + /** + * Pool maximum size. + */ + readonly size: number /** * Pool worker nodes. */ diff --git a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts index 3dda355e..2af13d63 100644 --- a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts @@ -1,5 +1,5 @@ import { DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS } from '../../utils' -import { type IPool, PoolType } from '../pool' +import type { IPool } from '../pool' import type { IWorker } from '../worker' import type { IWorkerChoiceStrategy, @@ -24,8 +24,6 @@ export abstract class AbstractWorkerChoiceStrategy< */ private toggleFindLastFreeWorkerNodeKey: boolean = false /** @inheritDoc */ - protected readonly isDynamicPool: boolean - /** @inheritDoc */ public readonly requiredStatistics: RequiredStatistics = { runTime: false, avgRunTime: false, @@ -42,7 +40,6 @@ export abstract class AbstractWorkerChoiceStrategy< protected readonly pool: IPool, protected opts: WorkerChoiceStrategyOptions = DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS ) { - this.isDynamicPool = this.pool.type === PoolType.DYNAMIC this.choose = this.choose.bind(this) } @@ -55,6 +52,14 @@ export abstract class AbstractWorkerChoiceStrategy< this.requiredStatistics.avgRunTime = true this.requiredStatistics.medRunTime = opts.medRunTime as boolean } + if ( + opts.weights != null && + Object.keys(opts.weights).length < this.pool.size + ) { + throw new Error( + 'Worker choice strategy options must have a weight for each worker node.' + ) + } } /** @inheritDoc */ diff --git a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts index f72ffb56..e42d54d9 100644 --- a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts @@ -39,12 +39,9 @@ export class FairShareWorkerChoiceStrategy< } /** - * Worker last virtual task execution timestamp. + * Workers' virtual task execution timestamp. */ - private readonly workerLastVirtualTaskTimestamp: Map< - number, - WorkerVirtualTaskTimestamp - > = new Map() + private workersVirtualTaskTimestamp: WorkerVirtualTaskTimestamp[] = [] /** @inheritDoc */ public constructor ( @@ -57,7 +54,7 @@ export class FairShareWorkerChoiceStrategy< /** @inheritDoc */ public reset (): boolean { - this.workerLastVirtualTaskTimestamp.clear() + this.workersVirtualTaskTimestamp = [] return true } @@ -65,15 +62,15 @@ export class FairShareWorkerChoiceStrategy< public choose (): number { let minWorkerVirtualTaskEndTimestamp = Infinity let chosenWorkerNodeKey!: number - for (const [index] of this.pool.workerNodes.entries()) { - this.computeWorkerLastVirtualTaskTimestamp(index) + for (const [workerNodeKey] of this.pool.workerNodes.entries()) { + this.computeWorkerVirtualTaskTimestamp(workerNodeKey) const workerLastVirtualTaskEndTimestamp = - this.workerLastVirtualTaskTimestamp.get(index)?.end ?? 0 + this.workersVirtualTaskTimestamp[workerNodeKey]?.end ?? 0 if ( workerLastVirtualTaskEndTimestamp < minWorkerVirtualTaskEndTimestamp ) { minWorkerVirtualTaskEndTimestamp = workerLastVirtualTaskEndTimestamp - chosenWorkerNodeKey = index + chosenWorkerNodeKey = workerNodeKey } } return chosenWorkerNodeKey @@ -81,31 +78,26 @@ export class FairShareWorkerChoiceStrategy< /** @inheritDoc */ public remove (workerNodeKey: number): boolean { - const deleted = this.workerLastVirtualTaskTimestamp.delete(workerNodeKey) - for (const [key, value] of this.workerLastVirtualTaskTimestamp) { - if (key > workerNodeKey) { - this.workerLastVirtualTaskTimestamp.set(key - 1, value) - } - } - return deleted + this.workersVirtualTaskTimestamp.splice(workerNodeKey, 1) + return true } /** - * Computes worker last virtual task timestamp. + * Computes worker virtual task timestamp. * * @param workerNodeKey - The worker node key. */ - private computeWorkerLastVirtualTaskTimestamp (workerNodeKey: number): void { + private computeWorkerVirtualTaskTimestamp (workerNodeKey: number): void { const workerVirtualTaskStartTimestamp = Math.max( performance.now(), - this.workerLastVirtualTaskTimestamp.get(workerNodeKey)?.end ?? -Infinity + this.workersVirtualTaskTimestamp[workerNodeKey]?.end ?? -Infinity ) const workerVirtualTaskTRunTime = this.requiredStatistics.medRunTime ? this.pool.workerNodes[workerNodeKey].tasksUsage.medRunTime : this.pool.workerNodes[workerNodeKey].tasksUsage.avgRunTime - this.workerLastVirtualTaskTimestamp.set(workerNodeKey, { + this.workersVirtualTaskTimestamp[workerNodeKey] = { start: workerVirtualTaskStartTimestamp, end: workerVirtualTaskStartTimestamp + (workerVirtualTaskTRunTime ?? 0) - }) + } } } diff --git a/src/pools/selection-strategies/less-busy-worker-choice-strategy.ts b/src/pools/selection-strategies/less-busy-worker-choice-strategy.ts index 10fc3bf7..79e65c59 100644 --- a/src/pools/selection-strategies/less-busy-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/less-busy-worker-choice-strategy.ts @@ -51,13 +51,13 @@ export class LessBusyWorkerChoiceStrategy< } let minRunTime = Infinity let lessBusyWorkerNodeKey!: number - for (const [index, workerNode] of this.pool.workerNodes.entries()) { + for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) { const workerRunTime = workerNode.tasksUsage.runTime if (workerRunTime === 0) { - return index + return workerNodeKey } else if (workerRunTime < minRunTime) { minRunTime = workerRunTime - lessBusyWorkerNodeKey = index + lessBusyWorkerNodeKey = workerNodeKey } } return lessBusyWorkerNodeKey diff --git a/src/pools/selection-strategies/less-used-worker-choice-strategy.ts b/src/pools/selection-strategies/less-used-worker-choice-strategy.ts index e3c395f4..1503e057 100644 --- a/src/pools/selection-strategies/less-used-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/less-used-worker-choice-strategy.ts @@ -43,14 +43,14 @@ export class LessUsedWorkerChoiceStrategy< } let minNumberOfTasks = Infinity let lessUsedWorkerNodeKey!: number - for (const [index, workerNode] of this.pool.workerNodes.entries()) { + for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) { const tasksUsage = workerNode.tasksUsage const workerTasks = tasksUsage.run + tasksUsage.running if (workerTasks === 0) { - return index + return workerNodeKey } else if (workerTasks < minNumberOfTasks) { minNumberOfTasks = workerTasks - lessUsedWorkerNodeKey = index + lessUsedWorkerNodeKey = workerNodeKey } } return lessUsedWorkerNodeKey diff --git a/src/pools/selection-strategies/selection-strategies-types.ts b/src/pools/selection-strategies/selection-strategies-types.ts index fa0d0f64..0e549cec 100644 --- a/src/pools/selection-strategies/selection-strategies-types.ts +++ b/src/pools/selection-strategies/selection-strategies-types.ts @@ -39,6 +39,13 @@ export interface WorkerChoiceStrategyOptions { * @defaultValue false */ medRunTime?: boolean + /** + * Worker weights to use for weighted round robin worker selection strategy. + * Weight is the tasks maximum average or median runtime in milliseconds. + * + * @defaultValue Computed worker weights automatically given the CPU performance. + */ + weights?: Record } /** diff --git a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts index 53b2d64d..b0750949 100644 --- a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts @@ -9,14 +9,6 @@ import type { WorkerChoiceStrategyOptions } from './selection-strategies-types' -/** - * Virtual task runtime. - */ -interface TaskRunTime { - weight: number - runTime: number -} - /** * Selects the next worker with a weighted round robin scheduling algorithm. * Loosely modeled after the weighted round robin queueing algorithm: https://en.wikipedia.org/wiki/Weighted_round_robin. @@ -48,12 +40,9 @@ export class WeightedRoundRobinWorkerChoiceStrategy< */ private readonly defaultWorkerWeight: number /** - * Workers' virtual task runtime. + * Worker virtual task runtime. */ - private readonly workersTaskRunTime: Map = new Map< - number, - TaskRunTime - >() + private workerVirtualTaskRunTime: number = 0 /** @inheritDoc */ public constructor ( @@ -62,45 +51,32 @@ export class WeightedRoundRobinWorkerChoiceStrategy< ) { super(pool, opts) this.checkOptions(this.opts) - this.defaultWorkerWeight = this.computeWorkerWeight() - this.initWorkersTaskRunTime() + this.defaultWorkerWeight = this.computeDefaultWorkerWeight() } /** @inheritDoc */ public reset (): boolean { this.currentWorkerNodeId = 0 - this.workersTaskRunTime.clear() - this.initWorkersTaskRunTime() + this.workerVirtualTaskRunTime = 0 return true } /** @inheritDoc */ public choose (): number { const chosenWorkerNodeKey = this.currentWorkerNodeId - if ( - this.isDynamicPool && - !this.workersTaskRunTime.has(chosenWorkerNodeKey) - ) { - this.initWorkerTaskRunTime(chosenWorkerNodeKey) - } - const workerTaskRunTime = - this.workersTaskRunTime.get(chosenWorkerNodeKey)?.runTime ?? 0 + const workerTaskRunTime = this.workerVirtualTaskRunTime ?? 0 const workerTaskWeight = - this.workersTaskRunTime.get(chosenWorkerNodeKey)?.weight ?? - this.defaultWorkerWeight + this.opts.weights?.[chosenWorkerNodeKey] ?? this.defaultWorkerWeight if (workerTaskRunTime < workerTaskWeight) { - this.setWorkerTaskRunTime( - chosenWorkerNodeKey, - workerTaskWeight, + this.workerVirtualTaskRunTime = workerTaskRunTime + - (this.getWorkerVirtualTaskRunTime(chosenWorkerNodeKey) ?? 0) - ) + (this.getWorkerVirtualTaskRunTime(chosenWorkerNodeKey) ?? 0) } else { this.currentWorkerNodeId = this.currentWorkerNodeId === this.pool.workerNodes.length - 1 ? 0 : this.currentWorkerNodeId + 1 - this.setWorkerTaskRunTime(this.currentWorkerNodeId, workerTaskWeight, 0) + this.workerVirtualTaskRunTime = 0 } return chosenWorkerNodeKey } @@ -116,35 +92,9 @@ export class WeightedRoundRobinWorkerChoiceStrategy< ? this.pool.workerNodes.length - 1 : this.currentWorkerNodeId } + this.workerVirtualTaskRunTime = 0 } - const deleted = this.workersTaskRunTime.delete(workerNodeKey) - for (const [key, value] of this.workersTaskRunTime) { - if (key > workerNodeKey) { - this.workersTaskRunTime.set(key - 1, value) - } - } - return deleted - } - - private initWorkersTaskRunTime (): void { - for (const [index] of this.pool.workerNodes.entries()) { - this.initWorkerTaskRunTime(index) - } - } - - private initWorkerTaskRunTime (workerNodeKey: number): void { - this.setWorkerTaskRunTime(workerNodeKey, this.defaultWorkerWeight, 0) - } - - private setWorkerTaskRunTime ( - workerNodeKey: number, - weight: number, - runTime: number - ): void { - this.workersTaskRunTime.set(workerNodeKey, { - weight, - runTime - }) + return true } private getWorkerVirtualTaskRunTime (workerNodeKey: number): number { @@ -153,7 +103,7 @@ export class WeightedRoundRobinWorkerChoiceStrategy< : this.pool.workerNodes[workerNodeKey].tasksUsage.avgRunTime } - private computeWorkerWeight (): number { + private computeDefaultWorkerWeight (): number { let cpusCycleTimeWeight = 0 for (const cpu of cpus()) { // CPU estimated cycle time diff --git a/src/pools/thread/dynamic.ts b/src/pools/thread/dynamic.ts index bb177f87..56b923c4 100644 --- a/src/pools/thread/dynamic.ts +++ b/src/pools/thread/dynamic.ts @@ -45,6 +45,11 @@ export class DynamicThreadPool< return this.workerNodes.length === this.max } + /** @inheritDoc */ + public get size (): number { + return this.max + } + /** @inheritDoc */ protected get busy (): boolean { return this.full && this.internalBusy() diff --git a/src/pools/thread/fixed.ts b/src/pools/thread/fixed.ts index 570c9c8b..41fcee2b 100644 --- a/src/pools/thread/fixed.ts +++ b/src/pools/thread/fixed.ts @@ -96,6 +96,11 @@ export class FixedThreadPool< return PoolType.FIXED } + /** @inheritDoc */ + public get size (): number { + return this.numberOfWorkers + } + /** @inheritDoc */ protected get full (): boolean { return this.workerNodes.length === this.numberOfWorkers diff --git a/tests/pools/selection-strategies/selection-strategies.test.js b/tests/pools/selection-strategies/selection-strategies.test.js index f5d41cc8..af63b3e9 100644 --- a/tests/pools/selection-strategies/selection-strategies.test.js +++ b/tests/pools/selection-strategies/selection-strategies.test.js @@ -77,20 +77,16 @@ describe('Selection strategies test suite', () => { ).nextWorkerNodeId ).toBe(0) } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) { - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).start - ).toBe(0) - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).end - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp + ).toBeInstanceOf(Array) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(0) } else if ( workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN ) { @@ -104,20 +100,11 @@ describe('Selection strategies test suite', () => { workerChoiceStrategy ).defaultWorkerWeight ).toBeGreaterThan(0) - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workersTaskRunTime.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workersTaskRunTime.get(workerNodeKey).weight - ).toBeGreaterThan(0) - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(workerChoiceStrategy) - .workersTaskRunTime.get(workerNodeKey).runTime - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBe(0) } } await pool.destroy() @@ -454,7 +441,7 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( pool.workerChoiceStrategyContext.workerChoiceStrategy - ).workerLastVirtualTaskTimestamp.size + ).workersVirtualTaskTimestamp.length ).toBe(pool.workerNodes.length) // We need to clean up the resources after our test await pool.destroy() @@ -474,13 +461,13 @@ describe('Selection strategies test suite', () => { promises.push(pool.execute()) } await Promise.all(promises) - // if (process.platform !== 'win32') { - // expect( - // pool.workerChoiceStrategyContext.workerChoiceStrategies.get( - // pool.workerChoiceStrategyContext.workerChoiceStrategy - // ).workerLastVirtualTaskTimestamp.size - // ).toBe(pool.workerNodes.length) - // } + if (process.platform !== 'win32') { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(pool.workerNodes.length) + } // We need to clean up the resources after our test await pool.destroy() }) @@ -510,13 +497,13 @@ describe('Selection strategies test suite', () => { expect(workerNode.tasksUsage.medRunTime).toBeDefined() expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0) } - // if (process.platform !== 'win32') { - // expect( - // pool.workerChoiceStrategyContext.workerChoiceStrategies.get( - // pool.workerChoiceStrategyContext.workerChoiceStrategy - // ).workerLastVirtualTaskTimestamp.size - // ).toBe(pool.workerNodes.length) - // } + if (process.platform !== 'win32') { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(pool.workerNodes.length) + } // We need to clean up the resources after our test await pool.destroy() }) @@ -530,23 +517,27 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy - ).workerLastVirtualTaskTimestamp - ).toBeDefined() + ).workersVirtualTaskTimestamp + ).toBeInstanceOf(Array) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(0) pool.setWorkerChoiceStrategy(workerChoiceStrategy) - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).start - ).toBe(0) - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).end - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp + ).toBeInstanceOf(Array) + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp[0] = 0 + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(1) await pool.destroy() pool = new DynamicThreadPool( min, @@ -556,23 +547,27 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy - ).workerLastVirtualTaskTimestamp - ).toBeDefined() + ).workersVirtualTaskTimestamp + ).toBeInstanceOf(Array) + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp[0] = 0 + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(1) pool.setWorkerChoiceStrategy(workerChoiceStrategy) - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).start - ).toBe(0) - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workerLastVirtualTaskTimestamp.get(workerNodeKey).end - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp + ).toBeInstanceOf(Array) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workersVirtualTaskTimestamp.length + ).toBe(0) // We need to clean up the resources after our test await pool.destroy() }) @@ -629,8 +624,13 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( pool.workerChoiceStrategyContext.workerChoiceStrategy - ).workersTaskRunTime.size - ).toBe(pool.workerNodes.length) + ).defaultWorkerWeight + ).toBeGreaterThan(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBeGreaterThanOrEqual(0) // We need to clean up the resources after our test await pool.destroy() }) @@ -656,8 +656,13 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( pool.workerChoiceStrategyContext.workerChoiceStrategy - ).workersTaskRunTime.size - ).toBe(pool.workerNodes.length) + ).defaultWorkerWeight + ).toBeGreaterThan(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBeGreaterThanOrEqual(0) } // We need to clean up the resources after our test await pool.destroy() @@ -688,13 +693,16 @@ describe('Selection strategies test suite', () => { expect(workerNode.tasksUsage.medRunTime).toBeDefined() expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0) } - // if (process.platform !== 'win32') { - // expect( - // pool.workerChoiceStrategyContext.workerChoiceStrategies.get( - // pool.workerChoiceStrategyContext.workerChoiceStrategy - // ).workersTaskRunTime.size - // ).toBe(pool.workerNodes.length) - // } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).defaultWorkerWeight + ).toBeGreaterThan(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + pool.workerChoiceStrategyContext.workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBeGreaterThanOrEqual(0) // We need to clean up the resources after our test await pool.destroy() }) @@ -718,7 +726,7 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy - ).workersTaskRunTime + ).workerVirtualTaskRunTime ).toBeDefined() pool.setWorkerChoiceStrategy(workerChoiceStrategy) expect( @@ -731,15 +739,11 @@ describe('Selection strategies test suite', () => { pool.workerChoiceStrategyContext.workerChoiceStrategy ).defaultWorkerWeight ).toBeGreaterThan(0) - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workersTaskRunTime.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workersTaskRunTime.get(workerNodeKey).runTime - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBe(0) await pool.destroy() pool = new DynamicThreadPool( min, @@ -759,7 +763,7 @@ describe('Selection strategies test suite', () => { expect( pool.workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy - ).workersTaskRunTime + ).workerVirtualTaskRunTime ).toBeDefined() pool.setWorkerChoiceStrategy(workerChoiceStrategy) expect( @@ -772,15 +776,11 @@ describe('Selection strategies test suite', () => { pool.workerChoiceStrategyContext.workerChoiceStrategy ).defaultWorkerWeight ).toBeGreaterThan(0) - for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workersTaskRunTime.keys()) { - expect( - pool.workerChoiceStrategyContext.workerChoiceStrategies - .get(pool.workerChoiceStrategyContext.workerChoiceStrategy) - .workersTaskRunTime.get(workerNodeKey).runTime - ).toBe(0) - } + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ).workerVirtualTaskRunTime + ).toBe(0) // We need to clean up the resources after our test await pool.destroy() }) diff --git a/tests/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.test.js b/tests/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.test.js index 8e59d81e..3f94411c 100644 --- a/tests/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.test.js +++ b/tests/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.test.js @@ -25,17 +25,17 @@ describe('Weighted round robin strategy worker choice strategy test suite', () = it('Verify that reset() resets internals', () => { const strategy = new WeightedRoundRobinWorkerChoiceStrategy(pool) - strategy.currentWorkerId = TestUtils.generateRandomInteger() - const workersTaskRunTimeClearStub = sinon - .stub(strategy.workersTaskRunTime, 'clear') - .returns() - const initWorkersTaskRunTimeStub = sinon - .stub(strategy, 'initWorkersTaskRunTime') - .returns() + strategy.currentWorkerId = TestUtils.generateRandomInteger( + Number.MAX_SAFE_INTEGER, + 1 + ) + strategy.workerVirtualTaskRunTime = TestUtils.generateRandomInteger( + Number.MAX_SAFE_INTEGER, + 1 + ) const resetResult = strategy.reset() expect(resetResult).toBe(true) expect(strategy.currentWorkerNodeId).toBe(0) - expect(workersTaskRunTimeClearStub.calledOnce).toBe(true) - expect(initWorkersTaskRunTimeStub.calledOnce).toBe(true) + expect(strategy.workerVirtualTaskRunTime).toBe(0) }) }) diff --git a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js index 79bcf2a1..060ebb63 100644 --- a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js +++ b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js @@ -116,11 +116,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(false) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy @@ -145,11 +140,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(true) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( workerChoiceStrategy @@ -174,11 +164,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(false) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -195,11 +180,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(true) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -216,11 +196,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(false) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -237,11 +212,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(true) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -258,11 +228,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(false) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -279,11 +244,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(true) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -300,11 +260,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(false) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( @@ -321,11 +276,6 @@ describe('Worker choice strategy context test suite', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - expect( - workerChoiceStrategyContext.workerChoiceStrategies.get( - workerChoiceStrategy - ).isDynamicPool - ).toBe(true) workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) expect( workerChoiceStrategyContext.workerChoiceStrategies.get( -- 2.34.1