feat: use monotonic high resolution timer for worker tasks statistics
authorJérôme Benoit <jerome.benoit@sap.com>
Sat, 8 Apr 2023 13:03:31 +0000 (15:03 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sat, 8 Apr 2023 13:03:31 +0000 (15:03 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
.eslintrc.js
CHANGELOG.md
src/pools/selection-strategies/fair-share-worker-choice-strategy.ts
src/worker/abstract-worker.ts

index 4fc348072f5fb5cb316c2130873d0018744baa8f..71acb042b00fe1eb99c786440fff67a10ebce48f 100644 (file)
@@ -46,6 +46,7 @@ module.exports = defineConfig({
           'esm',
           'fibonacci',
           'fs',
+          'hrtime',
           'inheritDoc',
           'jsdoc',
           'microjob',
index 52b7626f8fde4b6086c08ee5ba33e804cc313e4c..b2e14ab3b276f115407a0265d0405bda5bcf4b5c 100644 (file)
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Added
+
+- Use monotonic high resolution timer for worker tasks run time.
+- Add worker tasks median run time to statistics.
+
 ## [2.4.4] - 2023-04-07
 
 ### Added
index fc4f0f69032c7f37b2730bb7d68c4b6778f5f9a7..e16c1ea213d4de664273bdd1a3c2c05063537cba 100644 (file)
@@ -85,7 +85,7 @@ export class FairShareWorkerChoiceStrategy<
    */
   private computeWorkerLastVirtualTaskTimestamp (workerKey: number): void {
     const workerVirtualTaskStartTimestamp = Math.max(
-      Date.now(),
+      performance.now(),
       this.workerLastVirtualTaskTimestamp.get(workerKey)?.end ?? -Infinity
     )
     this.workerLastVirtualTaskTimestamp.set(workerKey, {
index 10a0c82d0565de18529343f163b295688c22bc70..b588b181fa1720bb44fc8b76d4dbafe847743364 100644 (file)
@@ -59,7 +59,7 @@ export abstract class AbstractWorker<
     this.checkFunctionInput(fn)
     this.checkWorkerOptions(this.opts)
     if (!this.isMain) {
-      this.lastTaskTimestamp = Date.now()
+      this.lastTaskTimestamp = performance.now()
       this.aliveInterval = setInterval(
         this.checkAlive.bind(this),
         (this.opts.maxInactiveTime ?? DEFAULT_MAX_INACTIVE_TIME) / 2
@@ -145,7 +145,7 @@ export abstract class AbstractWorker<
    */
   protected checkAlive (): void {
     if (
-      Date.now() - this.lastTaskTimestamp >
+      performance.now() - this.lastTaskTimestamp >
       (this.opts.maxInactiveTime ?? DEFAULT_MAX_INACTIVE_TIME)
     ) {
       this.sendToMainWorker({ kill: this.opts.killBehavior })
@@ -173,15 +173,19 @@ export abstract class AbstractWorker<
     message: MessageValue<Data>
   ): void {
     try {
-      const startTimestamp = Date.now()
+      const startTimestamp = performance.now()
       const res = fn(message.data)
-      const runTime = Date.now() - startTimestamp
-      this.sendToMainWorker({ data: res, id: message.id, runTime })
+      const runTime = performance.now() - startTimestamp
+      this.sendToMainWorker({
+        data: res,
+        id: message.id,
+        runTime
+      })
     } catch (e) {
       const err = this.handleError(e as Error)
       this.sendToMainWorker({ error: err, id: message.id })
     } finally {
-      !this.isMain && (this.lastTaskTimestamp = Date.now())
+      !this.isMain && (this.lastTaskTimestamp = performance.now())
     }
   }
 
@@ -195,11 +199,15 @@ export abstract class AbstractWorker<
     fn: (data?: Data) => Promise<Response>,
     message: MessageValue<Data>
   ): void {
-    const startTimestamp = Date.now()
+    const startTimestamp = performance.now()
     fn(message.data)
       .then(res => {
-        const runTime = Date.now() - startTimestamp
-        this.sendToMainWorker({ data: res, id: message.id, runTime })
+        const runTime = performance.now() - startTimestamp
+        this.sendToMainWorker({
+          data: res,
+          id: message.id,
+          runTime
+        })
         return null
       })
       .catch(e => {
@@ -207,7 +215,7 @@ export abstract class AbstractWorker<
         this.sendToMainWorker({ error: err, id: message.id })
       })
       .finally(() => {
-        !this.isMain && (this.lastTaskTimestamp = Date.now())
+        !this.isMain && (this.lastTaskTimestamp = performance.now())
       })
       .catch(EMPTY_FUNCTION)
   }