feat: add minimum and maximum to internal measurements
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 4 Jul 2023 18:28:58 +0000 (20:28 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 4 Jul 2023 18:28:58 +0000 (20:28 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
package.json
pnpm-lock.yaml
src/pools/abstract-pool.ts
src/pools/worker.ts
tests/pools/abstract/abstract-pool.test.js

index 903d0c6a58149cbf93f9da1ca22d2b82a1343bc9..02d47d0e21a6b209f702550294936c6df743fff9 100644 (file)
     "eslint-plugin-promise": "^6.1.1",
     "eslint-plugin-spellcheck": "^0.0.20",
     "eslint-plugin-tsdoc": "^0.2.17",
-    "expect": "^29.5.0",
+    "expect": "^29.6.0",
     "husky": "^8.0.3",
     "lint-staged": "^13.2.3",
     "microtime": "^3.1.1",
index 55a771263f0ae24aba16ce330546e485b43b3dbf..05a01f4319bd97cefcb9e285e8382497c7f7b79a 100644 (file)
@@ -72,8 +72,8 @@ devDependencies:
     specifier: ^0.2.17
     version: 0.2.17
   expect:
-    specifier: ^29.5.0
-    version: 29.5.0
+    specifier: ^29.6.0
+    version: 29.6.0
   husky:
     specifier: ^8.0.3
     version: 8.0.3
@@ -434,25 +434,25 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /@jest/expect-utils@29.5.0:
-    resolution: {integrity: sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==}
+  /@jest/expect-utils@29.6.0:
+    resolution: {integrity: sha512-LLSQQN7oypMSETKoPWpsWYVKJd9LQWmSDDAc4hUQ4JocVC7LAMy9R3ZMhlnLwbcFvQORZnZR7HM893Px6cJhvA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
       jest-get-type: 29.4.3
     dev: true
 
-  /@jest/schemas@29.4.3:
-    resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==}
+  /@jest/schemas@29.6.0:
+    resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@sinclair/typebox': 0.25.24
+      '@sinclair/typebox': 0.27.8
     dev: true
 
-  /@jest/types@29.5.0:
-    resolution: {integrity: sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==}
+  /@jest/types@29.6.0:
+    resolution: {integrity: sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@jest/schemas': 29.4.3
+      '@jest/schemas': 29.6.0
       '@types/istanbul-lib-coverage': 2.0.4
       '@types/istanbul-reports': 3.0.1
       '@types/node': 20.3.3
@@ -782,8 +782,8 @@ packages:
       rollup: 3.26.0
     dev: true
 
-  /@sinclair/typebox@0.25.24:
-    resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==}
+  /@sinclair/typebox@0.27.8:
+    resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
     dev: true
 
   /@sindresorhus/is@5.4.1:
@@ -2653,15 +2653,16 @@ packages:
       strip-final-newline: 3.0.0
     dev: true
 
-  /expect@29.5.0:
-    resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==}
+  /expect@29.6.0:
+    resolution: {integrity: sha512-AV+HaBtnDJ2YEUhPPo25HyUHBLaetM+y/Dq6pEC8VPQyt1dK+k8MfGkMy46djy2bddcqESc1kl4/K1uLWSfk9g==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@jest/expect-utils': 29.5.0
+      '@jest/expect-utils': 29.6.0
+      '@types/node': 20.3.3
       jest-get-type: 29.4.3
-      jest-matcher-utils: 29.5.0
-      jest-message-util: 29.5.0
-      jest-util: 29.5.0
+      jest-matcher-utils: 29.6.0
+      jest-message-util: 29.6.0
+      jest-util: 29.6.0
     dev: true
 
   /external-editor@3.1.0:
@@ -3677,14 +3678,14 @@ packages:
       iterate-iterator: 1.0.2
     dev: true
 
-  /jest-diff@29.5.0:
-    resolution: {integrity: sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==}
+  /jest-diff@29.6.0:
+    resolution: {integrity: sha512-ZRm7cd2m9YyZ0N3iMyuo1iUiprxQ/MFpYWXzEEj7hjzL3WnDffKW8192XBDcrAI8j7hnrM1wed3bL/oEnYF/8w==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
       chalk: 4.1.2
       diff-sequences: 29.4.3
       jest-get-type: 29.4.3
-      pretty-format: 29.5.0
+      pretty-format: 29.6.0
     dev: true
 
   /jest-get-type@29.4.3:
@@ -3692,36 +3693,36 @@ packages:
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dev: true
 
-  /jest-matcher-utils@29.5.0:
-    resolution: {integrity: sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==}
+  /jest-matcher-utils@29.6.0:
+    resolution: {integrity: sha512-oSlqfGN+sbkB2Q5um/zL7z80w84FEAcLKzXBZIPyRk2F2Srg1ubhrHVKW68JCvb2+xKzAeGw35b+6gciS24PHw==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
       chalk: 4.1.2
-      jest-diff: 29.5.0
+      jest-diff: 29.6.0
       jest-get-type: 29.4.3
-      pretty-format: 29.5.0
+      pretty-format: 29.6.0
     dev: true
 
-  /jest-message-util@29.5.0:
-    resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==}
+  /jest-message-util@29.6.0:
+    resolution: {integrity: sha512-mkCp56cETbpoNtsaeWVy6SKzk228mMi9FPHSObaRIhbR2Ujw9PqjW/yqVHD2tN1bHbC8ol6h3UEo7dOPmIYwIA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
       '@babel/code-frame': 7.22.5
-      '@jest/types': 29.5.0
+      '@jest/types': 29.6.0
       '@types/stack-utils': 2.0.1
       chalk: 4.1.2
       graceful-fs: 4.2.11
       micromatch: 4.0.5
-      pretty-format: 29.5.0
+      pretty-format: 29.6.0
       slash: 3.0.0
       stack-utils: 2.0.6
     dev: true
 
-  /jest-util@29.5.0:
-    resolution: {integrity: sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==}
+  /jest-util@29.6.0:
+    resolution: {integrity: sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@jest/types': 29.5.0
+      '@jest/types': 29.6.0
       '@types/node': 20.3.3
       chalk: 4.1.2
       ci-info: 3.8.0
@@ -4842,11 +4843,11 @@ packages:
     hasBin: true
     dev: true
 
-  /pretty-format@29.5.0:
-    resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==}
+  /pretty-format@29.6.0:
+    resolution: {integrity: sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@jest/schemas': 29.4.3
+      '@jest/schemas': 29.6.0
       ansi-styles: 5.2.0
       react-is: 18.2.0
     dev: true
index 283b04d682b4a656b6a430a78714a9ae52582e72..ad657b17cffd21b373473444a802fba34c6cefb8 100644 (file)
@@ -585,7 +585,16 @@ export abstract class AbstractPool<
       this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
         .aggregate
     ) {
-      workerUsage.runTime.aggregate += message.taskPerformance?.runTime ?? 0
+      const taskRunTime = message.taskPerformance?.runTime ?? 0
+      workerUsage.runTime.aggregate += taskRunTime
+      workerUsage.runTime.minimum = Math.min(
+        taskRunTime,
+        workerUsage.runTime.minimum
+      )
+      workerUsage.runTime.maximum = Math.max(
+        taskRunTime,
+        workerUsage.runTime.maximum
+      )
       if (
         this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
           .average &&
@@ -616,7 +625,15 @@ export abstract class AbstractPool<
       this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime
         .aggregate
     ) {
-      workerUsage.waitTime.aggregate += taskWaitTime ?? 0
+      workerUsage.waitTime.aggregate += taskWaitTime
+      workerUsage.waitTime.minimum = Math.min(
+        taskWaitTime,
+        workerUsage.waitTime.minimum
+      )
+      workerUsage.waitTime.maximum = Math.max(
+        taskWaitTime,
+        workerUsage.waitTime.maximum
+      )
       if (
         this.workerChoiceStrategyContext.getTaskStatisticsRequirements()
           .waitTime.average &&
@@ -645,17 +662,33 @@ export abstract class AbstractPool<
       this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu
         .aggregate
     ) {
-      if (workerUsage.elu != null && message.taskPerformance?.elu != null) {
+      if (message.taskPerformance?.elu != null) {
         workerUsage.elu.idle.aggregate += message.taskPerformance.elu.idle
         workerUsage.elu.active.aggregate += message.taskPerformance.elu.active
-        workerUsage.elu.utilization =
-          (workerUsage.elu.utilization +
-            message.taskPerformance.elu.utilization) /
-          2
-      } else if (message.taskPerformance?.elu != null) {
-        workerUsage.elu.idle.aggregate = message.taskPerformance.elu.idle
-        workerUsage.elu.active.aggregate = message.taskPerformance.elu.active
-        workerUsage.elu.utilization = message.taskPerformance.elu.utilization
+        if (workerUsage.elu.utilization != null) {
+          workerUsage.elu.utilization =
+            (workerUsage.elu.utilization +
+              message.taskPerformance.elu.utilization) /
+            2
+        } else {
+          workerUsage.elu.utilization = message.taskPerformance.elu.utilization
+        }
+        workerUsage.elu.idle.minimum = Math.min(
+          message.taskPerformance.elu.idle,
+          workerUsage.elu.idle.minimum
+        )
+        workerUsage.elu.idle.maximum = Math.max(
+          message.taskPerformance.elu.idle,
+          workerUsage.elu.idle.maximum
+        )
+        workerUsage.elu.active.minimum = Math.min(
+          message.taskPerformance.elu.active,
+          workerUsage.elu.active.minimum
+        )
+        workerUsage.elu.active.maximum = Math.max(
+          message.taskPerformance.elu.active,
+          workerUsage.elu.active.maximum
+        )
       }
       if (
         this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu
@@ -1062,12 +1095,16 @@ export abstract class AbstractPool<
       },
       runTime: {
         aggregate: 0,
+        maximum: 0,
+        minimum: 0,
         average: 0,
         median: 0,
         history: new CircularArray()
       },
       waitTime: {
         aggregate: 0,
+        maximum: 0,
+        minimum: 0,
         average: 0,
         median: 0,
         history: new CircularArray()
@@ -1075,17 +1112,20 @@ export abstract class AbstractPool<
       elu: {
         idle: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: new CircularArray()
         },
         active: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: new CircularArray()
-        },
-        utilization: 0
+        }
       }
     }
   }
index 93e4eda4c8e80aabfc1b13503e87ef4b0dc7173b..7f9cef0a6632aa354f07eb04db5dea6d7ad38c4e 100644 (file)
@@ -65,6 +65,14 @@ export interface MeasurementStatistics {
    * Measurement aggregate.
    */
   aggregate: number
+  /**
+   * Measurement minimum.
+   */
+  minimum: number
+  /**
+   * Measurement maximum.
+   */
+  maximum: number
   /**
    * Measurement average.
    */
@@ -87,7 +95,7 @@ export interface MeasurementStatistics {
 export interface EventLoopUtilizationMeasurementStatistics {
   readonly idle: MeasurementStatistics
   readonly active: MeasurementStatistics
-  utilization: number
+  utilization?: number
 }
 
 /**
index d3a71bc15f5f44e3fdbefe2f0c9d885e102caeed..d4b147f78f4cd13e62aedbf5a8cac0af8d56884a 100644 (file)
@@ -463,12 +463,16 @@ describe('Abstract pool test suite', () => {
         },
         runTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
         },
         waitTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
@@ -476,17 +480,20 @@ describe('Abstract pool test suite', () => {
         elu: {
           idle: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
           },
           active: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
-          },
-          utilization: 0
+          }
         }
       })
     }
@@ -528,12 +535,16 @@ describe('Abstract pool test suite', () => {
         },
         runTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
         },
         waitTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
@@ -541,17 +552,20 @@ describe('Abstract pool test suite', () => {
         elu: {
           idle: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
           },
           active: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
-          },
-          utilization: 0
+          }
         }
       })
     }
@@ -567,12 +581,16 @@ describe('Abstract pool test suite', () => {
         },
         runTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
         },
         waitTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
@@ -580,17 +598,20 @@ describe('Abstract pool test suite', () => {
         elu: {
           idle: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
           },
           active: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
-          },
-          utilization: 0
+          }
         }
       })
     }
@@ -620,12 +641,16 @@ describe('Abstract pool test suite', () => {
         },
         runTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
         },
         waitTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
@@ -633,17 +658,20 @@ describe('Abstract pool test suite', () => {
         elu: {
           idle: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
           },
           active: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
-          },
-          utilization: 0
+          }
         }
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThan(0)
@@ -661,12 +689,16 @@ describe('Abstract pool test suite', () => {
         },
         runTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
         },
         waitTime: {
           aggregate: 0,
+          maximum: 0,
+          minimum: 0,
           average: 0,
           median: 0,
           history: expect.any(CircularArray)
@@ -674,17 +706,20 @@ describe('Abstract pool test suite', () => {
         elu: {
           idle: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
           },
           active: {
             aggregate: 0,
+            maximum: 0,
+            minimum: 0,
             average: 0,
             median: 0,
             history: expect.any(CircularArray)
-          },
-          utilization: 0
+          }
         }
       })
       expect(workerNode.usage.runTime.history.length).toBe(0)