perf: pre-instantiate worker choice strategies
authorJérôme Benoit <jerome.benoit@sap.com>
Thu, 6 Apr 2023 06:40:41 +0000 (08:40 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Thu, 6 Apr 2023 06:40:41 +0000 (08:40 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/pools/abstract-pool.ts
src/pools/selection-strategies/worker-choice-strategy-context.ts
tests/pools/selection-strategies/selection-strategies.test.js
tests/pools/selection-strategies/worker-choice-strategy-context.test.js

index 7b0e5bc74e99b6268c27601002479c713545b3d7..476a523740807e14dc44a3c9d8ff5bc323d0b804 100644 (file)
@@ -142,6 +142,15 @@ export abstract class AbstractPool<
   private checkPoolOptions (opts: PoolOptions<Worker>): void {
     this.opts.workerChoiceStrategy =
       opts.workerChoiceStrategy ?? WorkerChoiceStrategies.ROUND_ROBIN
+    if (
+      !Object.values(WorkerChoiceStrategies).includes(
+        this.opts.workerChoiceStrategy
+      )
+    ) {
+      throw new Error(
+        `Invalid worker choice strategy '${this.opts.workerChoiceStrategy}'`
+      )
+    }
     this.opts.enableEvents = opts.enableEvents ?? true
   }
 
index 90c98c6018a1c786fda04234fd48eb5557b0edec..2d33738731c661e0df84a74a0ffa043e9e3b4e69 100644 (file)
@@ -24,10 +24,10 @@ export class WorkerChoiceStrategyContext<
   Data = unknown,
   Response = unknown
 > {
-  private readonly workerChoiceStrategies = new Map<
+  private readonly workerChoiceStrategies: Map<
   WorkerChoiceStrategy,
   IWorkerChoiceStrategy<Worker, Data, Response>
-  >()
+  >
 
   /**
    * Worker choice strategy context constructor.
@@ -42,7 +42,31 @@ export class WorkerChoiceStrategyContext<
     private workerChoiceStrategyType: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
   ) {
     this.execute.bind(this)
-    this.registerWorkerChoiceStrategy(pool, workerChoiceStrategyType)
+    this.workerChoiceStrategies = new Map<
+    WorkerChoiceStrategy,
+    IWorkerChoiceStrategy<Worker, Data, Response>
+    >([
+      [
+        WorkerChoiceStrategies.ROUND_ROBIN,
+        new RoundRobinWorkerChoiceStrategy<Worker, Data, Response>(pool)
+      ],
+      [
+        WorkerChoiceStrategies.LESS_USED,
+        new LessUsedWorkerChoiceStrategy<Worker, Data, Response>(pool)
+      ],
+      [
+        WorkerChoiceStrategies.LESS_BUSY,
+        new LessBusyWorkerChoiceStrategy<Worker, Data, Response>(pool)
+      ],
+      [
+        WorkerChoiceStrategies.FAIR_SHARE,
+        new FairShareWorkerChoiceStrategy<Worker, Data, Response>(pool)
+      ],
+      [
+        WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
+        new WeightedRoundRobinWorkerChoiceStrategy<Worker, Data, Response>(pool)
+      ]
+    ])
   }
 
   /**
@@ -71,7 +95,6 @@ export class WorkerChoiceStrategyContext<
       this.workerChoiceStrategies.get(workerChoiceStrategy)?.reset()
     } else {
       this.workerChoiceStrategyType = workerChoiceStrategy
-      this.registerWorkerChoiceStrategy(pool, workerChoiceStrategy)
     }
   }
 
@@ -107,50 +130,4 @@ export class WorkerChoiceStrategyContext<
       ) as IWorkerChoiceStrategy<Worker, Data, Response>
     ).remove(workerKey)
   }
-
-  private registerWorkerChoiceStrategy (
-    pool: IPoolInternal<Worker, Data, Response>,
-    workerChoiceStrategy: WorkerChoiceStrategy
-  ): void {
-    if (!this.workerChoiceStrategies.has(workerChoiceStrategy)) {
-      this.workerChoiceStrategies.set(
-        workerChoiceStrategy,
-        this.getWorkerChoiceStrategy(pool, workerChoiceStrategy)
-      )
-    }
-  }
-
-  /**
-   * Gets the worker choice strategy instance.
-   *
-   * @param pool - The pool instance.
-   * @param workerChoiceStrategy - The worker choice strategy.
-   * @returns The worker choice strategy instance.
-   */
-  private getWorkerChoiceStrategy (
-    pool: IPoolInternal<Worker, Data, Response>,
-    workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
-  ): IWorkerChoiceStrategy<Worker, Data, Response> {
-    switch (workerChoiceStrategy) {
-      case WorkerChoiceStrategies.ROUND_ROBIN:
-        return new RoundRobinWorkerChoiceStrategy<Worker, Data, Response>(pool)
-      case WorkerChoiceStrategies.LESS_USED:
-        return new LessUsedWorkerChoiceStrategy<Worker, Data, Response>(pool)
-      case WorkerChoiceStrategies.LESS_BUSY:
-        return new LessBusyWorkerChoiceStrategy<Worker, Data, Response>(pool)
-      case WorkerChoiceStrategies.FAIR_SHARE:
-        return new FairShareWorkerChoiceStrategy<Worker, Data, Response>(pool)
-      case WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN:
-        return new WeightedRoundRobinWorkerChoiceStrategy<
-        Worker,
-        Data,
-        Response
-        >(pool)
-      default:
-        throw new Error(
-          // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
-          `Worker choice strategy '${workerChoiceStrategy}' not found`
-        )
-    }
-  }
 }
index 254f02de7870e5c8da73ab6c260fa954a176283c..591b2c4d772a227676c469e0a857f4d8ca3a1a1d 100644 (file)
@@ -162,8 +162,8 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.ROUND_ROBIN
-      )?.nextWorkerId
-    ).toBeUndefined()
+      ).nextWorkerId
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -180,8 +180,8 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.ROUND_ROBIN
-      )?.nextWorkerId
-    ).toBeUndefined()
+      ).nextWorkerId
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -491,8 +491,8 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.FAIR_SHARE
-      )?.workerLastVirtualTaskTimestamp
-    ).toBeUndefined()
+      ).workerLastVirtualTaskTimestamp
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
     for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
       .get(WorkerChoiceStrategies.FAIR_SHARE)
@@ -517,8 +517,8 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.FAIR_SHARE
-      )?.workerLastVirtualTaskTimestamp
-    ).toBeUndefined()
+      ).workerLastVirtualTaskTimestamp
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
     for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
       .get(WorkerChoiceStrategies.FAIR_SHARE)
@@ -674,18 +674,18 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.currentWorkerId
-    ).toBeUndefined()
+      ).currentWorkerId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.defaultWorkerWeight
-    ).toBeUndefined()
+      ).defaultWorkerWeight
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.workersTaskRunTime
-    ).toBeUndefined()
+      ).workersTaskRunTime
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -715,18 +715,18 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.currentWorkerId
-    ).toBeUndefined()
+      ).currentWorkerId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.defaultWorkerWeight
-    ).toBeUndefined()
+      ).defaultWorkerWeight
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      )?.workersTaskRunTime
-    ).toBeUndefined()
+      ).workersTaskRunTime
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -761,7 +761,7 @@ describe('Selection strategies test suite', () => {
           { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
         )
     ).toThrowError(
-      new Error("Worker choice strategy 'UNKNOWN_STRATEGY' not found")
+      new Error("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
     )
   })
 })
index 0f02c363c0b2e3a90a5234faa2f4be4669b5959c..cdefafebcc56a42f7a66490ad0489eaadf9a5d9f 100644 (file)
@@ -297,82 +297,4 @@ describe('Worker choice strategy context test suite', () => {
       WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
     )
   })
-
-  it('Verify that getWorkerChoiceStrategy() default return ROUND_ROBIN strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy =
-      workerChoiceStrategyContext.getWorkerChoiceStrategy(fixedPool)
-    expect(strategy).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() can return ROUND_ROBIN strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy = workerChoiceStrategyContext.getWorkerChoiceStrategy(
-      fixedPool,
-      WorkerChoiceStrategies.ROUND_ROBIN
-    )
-    expect(strategy).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() can return LESS_USED strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy = workerChoiceStrategyContext.getWorkerChoiceStrategy(
-      fixedPool,
-      WorkerChoiceStrategies.LESS_USED
-    )
-    expect(strategy).toBeInstanceOf(LessUsedWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() can return LESS_BUSY strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy = workerChoiceStrategyContext.getWorkerChoiceStrategy(
-      fixedPool,
-      WorkerChoiceStrategies.LESS_BUSY
-    )
-    expect(strategy).toBeInstanceOf(LessBusyWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() can return FAIR_SHARE strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy = workerChoiceStrategyContext.getWorkerChoiceStrategy(
-      fixedPool,
-      WorkerChoiceStrategies.FAIR_SHARE
-    )
-    expect(strategy).toBeInstanceOf(FairShareWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() can return WEIGHTED_ROUND_ROBIN strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    const strategy = workerChoiceStrategyContext.getWorkerChoiceStrategy(
-      fixedPool,
-      WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-    )
-    expect(strategy).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy)
-  })
-
-  it('Verify that getWorkerChoiceStrategy() throw error on unknown strategy', () => {
-    const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
-      fixedPool
-    )
-    expect(() => {
-      workerChoiceStrategyContext.getWorkerChoiceStrategy(
-        fixedPool,
-        'UNKNOWN_STRATEGY'
-      )
-    }).toThrowError(
-      new Error("Worker choice strategy 'UNKNOWN_STRATEGY' not found")
-    )
-  })
 })