fix: fix pool information median computation
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 24 Aug 2023 18:00:43 +0000 (20:00 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 24 Aug 2023 18:00:43 +0000 (20:00 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
CHANGELOG.md
docs/worker-choice-strategies.md
src/pools/abstract-pool.ts
src/pools/pool.ts

index 811b839732be96b0b934d490f1b457922255b955..0e8866ffd0b5096aec3d5ce5ab1900cd3f4af8ea 100644 (file)
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Fixed
 
 - Don't account worker usage statistics for tasks that have failed.
+- Fix pool information runtime and wait time median computation.
 
 ### Changed
 
index 296d8c3b1cc7370058577d654d44625d9d3cfe13..a2b035f7890dadd28183db92b5f17c8546e5af2e 100644 (file)
@@ -34,4 +34,4 @@ Worker choice strategies enable only the statistics that are needed to choose th
 
 ### Simple moving median
 
-Strategies using the average task execution time for each worker can use the simple moving median instead. Simple moving median is more robust to outliers and can be used to avoid assigning tasks to workers that are currently overloaded. Simple moving median usage introduces a small overhead: measurement history must be kept for each worker and the simple moving median must be recomputed each time a task has finished.
+Strategies using the simple moving average task execution time for each worker can use the simple moving median instead. Simple moving median is more robust to outliers and can be used to avoid assigning tasks to workers that are currently overloaded.
index a11a574147cf074dc938d1e0d47b3797e6e15ad2..8c202696cd03d01b4e1c02163bfd32930c2ea141 100644 (file)
@@ -427,21 +427,26 @@ export abstract class AbstractPool<
               )
             )
           ),
-          average: round(
-            average(
-              this.workerNodes.reduce<number[]>(
-                (accumulator, workerNode) =>
-                  accumulator.concat(workerNode.usage.runTime.history),
-                []
+          ...(this.workerChoiceStrategyContext.getTaskStatisticsRequirements()
+            .runTime.average && {
+            average: round(
+              average(
+                this.workerNodes.reduce<number[]>(
+                  (accumulator, workerNode) =>
+                    accumulator.concat(workerNode.usage.runTime.history),
+                  []
+                )
               )
             )
-          ),
+          }),
           ...(this.workerChoiceStrategyContext.getTaskStatisticsRequirements()
             .runTime.median && {
             median: round(
               median(
-                this.workerNodes.map(
-                  (workerNode) => workerNode.usage.runTime?.median ?? 0
+                this.workerNodes.reduce<number[]>(
+                  (accumulator, workerNode) =>
+                    accumulator.concat(workerNode.usage.runTime.history),
+                  []
                 )
               )
             )
@@ -465,21 +470,26 @@ export abstract class AbstractPool<
               )
             )
           ),
-          average: round(
-            average(
-              this.workerNodes.reduce<number[]>(
-                (accumulator, workerNode) =>
-                  accumulator.concat(workerNode.usage.waitTime.history),
-                []
+          ...(this.workerChoiceStrategyContext.getTaskStatisticsRequirements()
+            .waitTime.average && {
+            average: round(
+              average(
+                this.workerNodes.reduce<number[]>(
+                  (accumulator, workerNode) =>
+                    accumulator.concat(workerNode.usage.waitTime.history),
+                  []
+                )
               )
             )
-          ),
+          }),
           ...(this.workerChoiceStrategyContext.getTaskStatisticsRequirements()
             .waitTime.median && {
             median: round(
               median(
-                this.workerNodes.map(
-                  (workerNode) => workerNode.usage.waitTime?.median ?? 0
+                this.workerNodes.reduce<number[]>(
+                  (accumulator, workerNode) =>
+                    accumulator.concat(workerNode.usage.waitTime.history),
+                  []
                 )
               )
             )
index fb59d37a19892e8eb8cb979bbc69454eaae4a35b..7b5498096315988a93c247223ef582af6a5f99f0 100644 (file)
@@ -84,13 +84,13 @@ export interface PoolInfo {
   readonly runTime?: {
     readonly minimum: number
     readonly maximum: number
-    readonly average: number
+    readonly average?: number
     readonly median?: number
   }
   readonly waitTime?: {
     readonly minimum: number
     readonly maximum: number
-    readonly average: number
+    readonly average?: number
     readonly median?: number
   }
 }