perf: use optimized circular buffer implementation to store measurements history
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 21 May 2024 19:38:17 +0000 (21:38 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 21 May 2024 19:38:17 +0000 (21:38 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
16 files changed:
.eslintrc.cjs
package.json
pnpm-lock.yaml
src/circular-array.ts [deleted file]
src/circular-buffer.ts [new file with mode: 0644]
src/index.ts
src/pools/abstract-pool.ts
src/pools/utils.ts
src/pools/worker-node.ts
src/pools/worker.ts
tests/circular-array.test.mjs [deleted file]
tests/circular-buffer.test.mjs [new file with mode: 0644]
tests/pools/abstract-pool.test.mjs
tests/pools/selection-strategies/selection-strategies.test.mjs
tests/pools/utils.test.mjs
tests/pools/worker-node.test.mjs

index 80b400b6572173a3817bd88651cd85b5b9369e62..a28991af3dbe005be30c1b283d03352ba0a79fc6 100644 (file)
@@ -64,6 +64,7 @@ module.exports = defineConfig({
           'fp',
           'fs',
           'func',
+          'idx',
           'inheritDoc',
           'javascript',
           'jsdoc',
index 2bd516ba5d6a30c94e0493f7bf3c7a4b4384e9bd..fa276bb3b76e295932cfc6ede7a2b659dd6741d3 100644 (file)
     "eslint-plugin-tsdoc": "^0.2.17",
     "expect": "^29.7.0",
     "husky": "^9.0.11",
-    "lint-staged": "^15.2.2",
-    "microtime": "^3.1.1",
+    "lint-staged": "^15.2.4",
     "mocha": "^10.4.0",
     "mochawesome": "^7.1.3",
     "prettier": "^3.2.5",
index f3e2c5cd32068ecf7c54152ed71e8daf39bb0222..1e0ba7cb1664375d2fcce89bd386773b61f9993d 100644 (file)
@@ -90,11 +90,8 @@ importers:
         specifier: ^9.0.11
         version: 9.0.11
       lint-staged:
-        specifier: ^15.2.2
-        version: 15.2.2
-      microtime:
-        specifier: ^3.1.1
-        version: 3.1.1
+        specifier: ^15.2.4
+        version: 15.2.4
       mocha:
         specifier: ^10.4.0
         version: 10.4.0
@@ -984,9 +981,9 @@ packages:
   colorette@2.0.20:
     resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
 
-  commander@11.1.0:
-    resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
-    engines: {node: '>=16'}
+  commander@12.1.0:
+    resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
+    engines: {node: '>=18'}
 
   commander@2.20.3:
     resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -2082,20 +2079,20 @@ packages:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
 
-  lilconfig@3.0.0:
-    resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+  lilconfig@3.1.1:
+    resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==}
     engines: {node: '>=14'}
 
   lines-and-columns@1.2.4:
     resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
 
-  lint-staged@15.2.2:
-    resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==}
+  lint-staged@15.2.4:
+    resolution: {integrity: sha512-3F9KRQIS2fVDGtCkBp4Bx0jswjX7zUcKx6OF0ZeY1prksUyKPRIIUqZhIUYAstJfvj6i48VFs4dwVIbCYwvTYQ==}
     engines: {node: '>=18.12.0'}
     hasBin: true
 
-  listr2@8.0.1:
-    resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==}
+  listr2@8.2.1:
+    resolution: {integrity: sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==}
     engines: {node: '>=18.0.0'}
 
   locate-path@6.0.0:
@@ -2217,14 +2214,10 @@ packages:
     resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
     engines: {node: '>= 8'}
 
-  micromatch@4.0.5:
-    resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+  micromatch@4.0.6:
+    resolution: {integrity: sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==}
     engines: {node: '>=8.6'}
 
-  microtime@3.1.1:
-    resolution: {integrity: sha512-to1r7o24cDsud9IhN6/8wGmMx5R2kT0w2Xwm5okbYI3d1dk6Xv0m+Z+jg2vS9pt+ocgQHTCtgs/YuyJhySzxNg==}
-    engines: {node: '>= 14.13.0'}
-
   mime-db@1.52.0:
     resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
     engines: {node: '>= 0.6'}
@@ -2301,9 +2294,6 @@ packages:
   nise@6.0.0:
     resolution: {integrity: sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==}
 
-  node-addon-api@5.1.0:
-    resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
-
   node-domexception@1.0.0:
     resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
     engines: {node: '>=10.5.0'}
@@ -2312,10 +2302,6 @@ packages:
     resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
-  node-gyp-build@4.8.1:
-    resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
-    hasBin: true
-
   normalize-path@3.0.0:
     resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
     engines: {node: '>=0.10.0'}
@@ -2489,6 +2475,10 @@ packages:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     engines: {node: '>=8.6'}
 
+  picomatch@4.0.2:
+    resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
+    engines: {node: '>=12'}
+
   pidtree@0.6.0:
     resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
     engines: {node: '>=0.10'}
@@ -3120,9 +3110,10 @@ packages:
     resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
     engines: {node: '>=10'}
 
-  yaml@2.3.4:
-    resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
+  yaml@2.4.2:
+    resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==}
     engines: {node: '>= 14'}
+    hasBin: true
 
   yargs-parser@20.2.4:
     resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
@@ -4077,7 +4068,7 @@ snapshots:
 
   colorette@2.0.20: {}
 
-  commander@11.1.0: {}
+  commander@12.1.0: {}
 
   commander@2.20.3: {}
 
@@ -4663,7 +4654,7 @@ snapshots:
       '@nodelib/fs.walk': 1.2.8
       glob-parent: 5.1.2
       merge2: 1.4.1
-      micromatch: 4.0.5
+      micromatch: 4.0.6
 
   fast-json-stable-stringify@2.1.0: {}
 
@@ -5239,7 +5230,7 @@ snapshots:
       '@types/stack-utils': 2.0.3
       chalk: 4.1.2
       graceful-fs: 4.2.11
-      micromatch: 4.0.5
+      micromatch: 4.0.6
       pretty-format: 29.7.0
       slash: 3.0.0
       stack-utils: 2.0.6
@@ -5308,26 +5299,26 @@ snapshots:
       prelude-ls: 1.2.1
       type-check: 0.4.0
 
-  lilconfig@3.0.0: {}
+  lilconfig@3.1.1: {}
 
   lines-and-columns@1.2.4: {}
 
-  lint-staged@15.2.2:
+  lint-staged@15.2.4:
     dependencies:
       chalk: 5.3.0
-      commander: 11.1.0
+      commander: 12.1.0
       debug: 4.3.4(supports-color@8.1.1)
       execa: 8.0.1
-      lilconfig: 3.0.0
-      listr2: 8.0.1
-      micromatch: 4.0.5
+      lilconfig: 3.1.1
+      listr2: 8.2.1
+      micromatch: 4.0.6
       pidtree: 0.6.0
       string-argv: 0.3.2
-      yaml: 2.3.4
+      yaml: 2.4.2
     transitivePeerDependencies:
       - supports-color
 
-  listr2@8.0.1:
+  listr2@8.2.1:
     dependencies:
       cli-truncate: 4.0.0
       colorette: 2.0.20
@@ -5428,15 +5419,10 @@ snapshots:
 
   merge2@1.4.1: {}
 
-  micromatch@4.0.5:
+  micromatch@4.0.6:
     dependencies:
       braces: 3.0.3
-      picomatch: 2.3.1
-
-  microtime@3.1.1:
-    dependencies:
-      node-addon-api: 5.1.0
-      node-gyp-build: 4.8.1
+      picomatch: 4.0.2
 
   mime-db@1.52.0: {}
 
@@ -5540,8 +5526,6 @@ snapshots:
       just-extend: 6.2.0
       path-to-regexp: 6.2.2
 
-  node-addon-api@5.1.0: {}
-
   node-domexception@1.0.0: {}
 
   node-fetch@3.3.2:
@@ -5550,8 +5534,6 @@ snapshots:
       fetch-blob: 3.2.0
       formdata-polyfill: 4.0.10
 
-  node-gyp-build@4.8.1: {}
-
   normalize-path@3.0.0: {}
 
   normalize-url@8.0.1: {}
@@ -5745,6 +5727,8 @@ snapshots:
 
   picomatch@2.3.1: {}
 
+  picomatch@4.0.2: {}
+
   pidtree@0.6.0: {}
 
   possible-typed-array-names@1.0.0: {}
@@ -6446,7 +6430,7 @@ snapshots:
 
   y18n@5.0.8: {}
 
-  yaml@2.3.4: {}
+  yaml@2.4.2: {}
 
   yargs-parser@20.2.4: {}
 
diff --git a/src/circular-array.ts b/src/circular-array.ts
deleted file mode 100644 (file)
index 2347327..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
-
-export const DEFAULT_CIRCULAR_ARRAY_SIZE = 385
-
-/**
- * Array with a maximum length and shifting items when full.
- *
- * @typeParam T - Type of items.
- * @internal
- */
-export class CircularArray<T> extends Array<T> {
-  public size: number
-
-  constructor (size: number = DEFAULT_CIRCULAR_ARRAY_SIZE, ...items: T[]) {
-    super()
-    this.checkSize(size)
-    this.size = size
-    if (arguments.length > 1) {
-      this.push(...items)
-    }
-  }
-
-  /** @inheritDoc */
-  public push (...items: T[]): number {
-    const length = super.push(...items)
-    if (length > this.size) {
-      super.splice(0, length - this.size)
-    }
-    return this.length
-  }
-
-  /** @inheritDoc */
-  public unshift (...items: T[]): number {
-    const length = super.unshift(...items)
-    if (length > this.size) {
-      super.splice(this.size, items.length)
-    }
-    return this.length
-  }
-
-  /** @inheritDoc */
-  public concat (...items: Array<T | ConcatArray<T>>): CircularArray<T> {
-    const concatenatedCircularArray = super.concat(
-      items as T[]
-    ) as CircularArray<T>
-    concatenatedCircularArray.size = this.size
-    if (concatenatedCircularArray.length > concatenatedCircularArray.size) {
-      concatenatedCircularArray.splice(
-        0,
-        concatenatedCircularArray.length - concatenatedCircularArray.size
-      )
-    }
-    return concatenatedCircularArray
-  }
-
-  /** @inheritDoc */
-  public splice (
-    start: number,
-    deleteCount?: number,
-    ...items: T[]
-  ): CircularArray<T> {
-    let itemsRemoved: T[] = []
-    if (arguments.length >= 3 && deleteCount != null) {
-      itemsRemoved = super.splice(start, deleteCount, ...items)
-      if (this.length > this.size) {
-        const itemsOverflowing = super.splice(0, this.length - this.size)
-        itemsRemoved = new CircularArray<T>(
-          itemsRemoved.length + itemsOverflowing.length,
-          ...itemsRemoved,
-          ...itemsOverflowing
-        )
-      }
-    } else if (arguments.length === 2) {
-      itemsRemoved = super.splice(start, deleteCount)
-    } else {
-      itemsRemoved = super.splice(start)
-    }
-    return itemsRemoved as CircularArray<T>
-  }
-
-  public resize (size: number): void {
-    this.checkSize(size)
-    if (size === 0) {
-      this.length = 0
-    } else if (size < this.size) {
-      for (let i = size; i < this.size; i++) {
-        super.pop()
-      }
-    }
-    this.size = size
-  }
-
-  public empty (): boolean {
-    return this.length === 0
-  }
-
-  public full (): boolean {
-    return this.length === this.size
-  }
-
-  private checkSize (size: number): void {
-    if (!Number.isSafeInteger(size)) {
-      throw new TypeError(
-        `Invalid circular array size: ${size} is not a safe integer`
-      )
-    }
-    if (size < 0) {
-      throw new RangeError(`Invalid circular array size: ${size} < 0`)
-    }
-  }
-}
diff --git a/src/circular-buffer.ts b/src/circular-buffer.ts
new file mode 100644 (file)
index 0000000..cbe733d
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * Default buffer size
+ */
+export const defaultBufferSize = 2048
+
+/**
+ * Circular buffer
+ */
+export class CircularBuffer<T> {
+  private readonly readIdx: number
+  private writeIdx: number
+  private items: Array<T | undefined>
+  private readonly maxArrayIdx: number
+
+  /**
+   * @param size - Buffer size
+   * @returns CircularBuffer
+   */
+  constructor (size: number = defaultBufferSize) {
+    this.checkSize(size)
+    this.readIdx = 0
+    this.writeIdx = 0
+    this.maxArrayIdx = size - 1
+    this.items = new Array<T | undefined>(size)
+  }
+
+  /**
+   * Puts data into buffer
+   *
+   * @param data - Data to push
+   */
+  public put (data: T): void {
+    this.items[this.writeIdx] = data
+    this.writeIdx = this.writeIdx === this.maxArrayIdx ? 0 : this.writeIdx + 1
+  }
+
+  /**
+   * Returns buffer as array
+   *
+   * @returns T[]
+   */
+  public toArray (): T[] {
+    return this.items.filter(item => item != null) as T[]
+  }
+
+  private checkSize (size: number): void {
+    if (!Number.isSafeInteger(size)) {
+      throw new TypeError(
+        `Invalid circular buffer size: ${size} is not an integer`
+      )
+    }
+    if (size < 0) {
+      throw new RangeError(`Invalid circular buffer size: ${size} < 0`)
+    }
+  }
+}
index cba064140d08ba8912d516f3c4a9c70745def408..fae19abdbf8766739d4ded4b0014bbb53d6ebadd 100644 (file)
@@ -1,4 +1,4 @@
-export type { CircularArray } from './circular-array.js'
+export type { CircularBuffer } from './circular-buffer.js'
 export type { AbstractPool } from './pools/abstract-pool.js'
 export { DynamicClusterPool } from './pools/cluster/dynamic.js'
 export type { ClusterPoolOptions } from './pools/cluster/fixed.js'
index a23c7983bfc652fbfcb8ece4a75853dbed270ac5..a7d3e944522e90d5ee5dce103be13cd5e334bdc4 100644 (file)
@@ -395,7 +395,9 @@ export abstract class AbstractPool<
               average(
                 this.workerNodes.reduce<number[]>(
                   (accumulator, workerNode) =>
-                    accumulator.concat(workerNode.usage.runTime.history),
+                    accumulator.concat(
+                      workerNode.usage.runTime.history.toArray()
+                    ),
                   []
                 )
               )
@@ -407,7 +409,9 @@ export abstract class AbstractPool<
               median(
                 this.workerNodes.reduce<number[]>(
                   (accumulator, workerNode) =>
-                    accumulator.concat(workerNode.usage.runTime.history),
+                    accumulator.concat(
+                      workerNode.usage.runTime.history.toArray()
+                    ),
                   []
                 )
               )
@@ -440,7 +444,9 @@ export abstract class AbstractPool<
               average(
                 this.workerNodes.reduce<number[]>(
                   (accumulator, workerNode) =>
-                    accumulator.concat(workerNode.usage.waitTime.history),
+                    accumulator.concat(
+                      workerNode.usage.waitTime.history.toArray()
+                    ),
                   []
                 )
               )
@@ -452,7 +458,9 @@ export abstract class AbstractPool<
               median(
                 this.workerNodes.reduce<number[]>(
                   (accumulator, workerNode) =>
-                    accumulator.concat(workerNode.usage.waitTime.history),
+                    accumulator.concat(
+                      workerNode.usage.waitTime.history.toArray()
+                    ),
                   []
                 )
               )
@@ -488,7 +496,9 @@ export abstract class AbstractPool<
                 average(
                   this.workerNodes.reduce<number[]>(
                     (accumulator, workerNode) =>
-                      accumulator.concat(workerNode.usage.elu.idle.history),
+                      accumulator.concat(
+                        workerNode.usage.elu.idle.history.toArray()
+                      ),
                     []
                   )
                 )
@@ -500,7 +510,9 @@ export abstract class AbstractPool<
                 median(
                   this.workerNodes.reduce<number[]>(
                     (accumulator, workerNode) =>
-                      accumulator.concat(workerNode.usage.elu.idle.history),
+                      accumulator.concat(
+                        workerNode.usage.elu.idle.history.toArray()
+                      ),
                     []
                   )
                 )
@@ -532,7 +544,9 @@ export abstract class AbstractPool<
                 average(
                   this.workerNodes.reduce<number[]>(
                     (accumulator, workerNode) =>
-                      accumulator.concat(workerNode.usage.elu.active.history),
+                      accumulator.concat(
+                        workerNode.usage.elu.active.history.toArray()
+                      ),
                     []
                   )
                 )
@@ -544,7 +558,9 @@ export abstract class AbstractPool<
                 median(
                   this.workerNodes.reduce<number[]>(
                     (accumulator, workerNode) =>
-                      accumulator.concat(workerNode.usage.elu.active.history),
+                      accumulator.concat(
+                        workerNode.usage.elu.active.history.toArray()
+                      ),
                     []
                   )
                 )
index e69725df102ed2ea083512b76f5dce75139a6894..f2ede8b6d2b07d44316cfdaa14abd91cb10204cc 100644 (file)
@@ -233,14 +233,18 @@ const updateMeasurementStatistics = (
       measurementStatistics.maximum ?? Number.NEGATIVE_INFINITY
     )
     if (measurementRequirements.average || measurementRequirements.median) {
-      measurementStatistics.history.push(measurementValue)
+      measurementStatistics.history.put(measurementValue)
       if (measurementRequirements.average) {
-        measurementStatistics.average = average(measurementStatistics.history)
+        measurementStatistics.average = average(
+          measurementStatistics.history.toArray()
+        )
       } else if (measurementStatistics.average != null) {
         delete measurementStatistics.average
       }
       if (measurementRequirements.median) {
-        measurementStatistics.median = median(measurementStatistics.history)
+        measurementStatistics.median = median(
+          measurementStatistics.history.toArray()
+        )
       } else if (measurementStatistics.median != null) {
         delete measurementStatistics.median
       }
index c1c1e0a99b2bc3200e58e85d7c8d1b29aacaa893..d87a79c099c5dab34126e284ca2f14f4be72b3a1 100644 (file)
@@ -1,7 +1,7 @@
 import { EventEmitter } from 'node:events'
 import { MessageChannel } from 'node:worker_threads'
 
-import { CircularArray } from '../circular-array.js'
+import { CircularBuffer } from '../circular-buffer.js'
 import { PriorityQueue } from '../priority-queue.js'
 import type { Task } from '../utility-types.js'
 import { DEFAULT_TASK_NAME } from '../utils.js'
@@ -15,6 +15,7 @@ import {
   type EventHandler,
   type IWorker,
   type IWorkerNode,
+  MeasurementHistorySize,
   type StrategyData,
   type WorkerInfo,
   type WorkerNodeOptions,
@@ -239,17 +240,17 @@ export class WorkerNode<Worker extends IWorker, Data = unknown>
         failed: 0
       },
       runTime: {
-        history: new CircularArray<number>()
+        history: new CircularBuffer<number>(MeasurementHistorySize)
       },
       waitTime: {
-        history: new CircularArray<number>()
+        history: new CircularBuffer<number>(MeasurementHistorySize)
       },
       elu: {
         idle: {
-          history: new CircularArray<number>()
+          history: new CircularBuffer<number>(MeasurementHistorySize)
         },
         active: {
-          history: new CircularArray<number>()
+          history: new CircularBuffer<number>(MeasurementHistorySize)
         }
       }
     }
@@ -282,17 +283,17 @@ export class WorkerNode<Worker extends IWorker, Data = unknown>
         failed: 0
       },
       runTime: {
-        history: new CircularArray<number>()
+        history: new CircularBuffer<number>(MeasurementHistorySize)
       },
       waitTime: {
-        history: new CircularArray<number>()
+        history: new CircularBuffer<number>(MeasurementHistorySize)
       },
       elu: {
         idle: {
-          history: new CircularArray<number>()
+          history: new CircularBuffer<number>(MeasurementHistorySize)
         },
         active: {
-          history: new CircularArray<number>()
+          history: new CircularBuffer<number>(MeasurementHistorySize)
         }
       }
     }
index 99c0d9a6feeea35815a520ff95a160d927bcc4fc..7d9f3de9b24e2a8cebeed50064ff2e8ab87e71b8 100644 (file)
@@ -1,7 +1,7 @@
 import type { EventEmitter } from 'node:events'
 import type { MessageChannel, WorkerOptions } from 'node:worker_threads'
 
-import type { CircularArray } from '../circular-array.js'
+import type { CircularBuffer } from '../circular-buffer.js'
 import type { Task, TaskFunctionProperties } from '../utility-types.js'
 
 /**
@@ -52,6 +52,11 @@ export type EventHandler<Worker extends IWorker> =
   | ErrorHandler<Worker>
   | ExitHandler<Worker>
 
+/**
+ * Measurement history size.
+ */
+export const MeasurementHistorySize = 386
+
 /**
  * Measurement statistics.
  *
@@ -81,7 +86,7 @@ export interface MeasurementStatistics {
   /**
    * Measurement history.
    */
-  readonly history: CircularArray<number>
+  readonly history: CircularBuffer<number>
 }
 
 /**
diff --git a/tests/circular-array.test.mjs b/tests/circular-array.test.mjs
deleted file mode 100644 (file)
index a6f2f69..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-import { expect } from 'expect'
-
-import {
-  CircularArray,
-  DEFAULT_CIRCULAR_ARRAY_SIZE
-} from '../lib/circular-array.cjs'
-
-describe('Circular array test suite', () => {
-  it('Verify that circular array can be instantiated', () => {
-    const circularArray = new CircularArray()
-    expect(circularArray).toBeInstanceOf(CircularArray)
-  })
-
-  it('Verify circular array default size at instance creation', () => {
-    const circularArray = new CircularArray()
-    expect(circularArray.size).toBe(DEFAULT_CIRCULAR_ARRAY_SIZE)
-  })
-
-  it('Verify that circular array size can be set at instance creation', () => {
-    const circularArray = new CircularArray(1000)
-    expect(circularArray.size).toBe(1000)
-  })
-
-  it('Verify that circular array size and items can be set at instance creation', () => {
-    let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
-    expect(circularArray.size).toBe(1000)
-    expect(circularArray.length).toBe(5)
-    circularArray = new CircularArray(4, 1, 2, 3, 4, 5)
-    expect(circularArray.size).toBe(4)
-    expect(circularArray.length).toBe(4)
-  })
-
-  it('Verify that circular array size is valid at instance creation', () => {
-    expect(() => new CircularArray(0.25)).toThrow(
-      new TypeError('Invalid circular array size: 0.25 is not a safe integer')
-    )
-    expect(() => new CircularArray(-1)).toThrow(
-      new RangeError('Invalid circular array size: -1 < 0')
-    )
-    expect(() => new CircularArray(Number.MAX_SAFE_INTEGER + 1)).toThrow(
-      new TypeError(
-        `Invalid circular array size: ${
-          Number.MAX_SAFE_INTEGER + 1
-        } is not a safe integer`
-      )
-    )
-  })
-
-  it('Verify that circular array empty works as intended', () => {
-    const circularArray = new CircularArray()
-    expect(circularArray.empty()).toBe(true)
-  })
-
-  it('Verify that circular array full works as intended', () => {
-    const circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    expect(circularArray.full()).toBe(true)
-  })
-
-  it('Verify that circular array push works as intended', () => {
-    let circularArray = new CircularArray(4)
-    let arrayLength = circularArray.push(1, 2, 3, 4, 5)
-    expect(arrayLength).toBe(circularArray.size)
-    expect(circularArray.length).toBe(circularArray.size)
-    expect(circularArray).toStrictEqual(new CircularArray(4, 2, 3, 4, 5))
-    arrayLength = circularArray.push(6, 7)
-    expect(arrayLength).toBe(circularArray.size)
-    expect(circularArray.length).toBe(circularArray.size)
-    expect(circularArray).toStrictEqual(new CircularArray(4, 4, 5, 6, 7))
-    circularArray = new CircularArray(100)
-    arrayLength = circularArray.push(1, 2, 3, 4, 5)
-    expect(arrayLength).toBe(5)
-    expect(circularArray.size).toBe(100)
-    expect(circularArray.length).toBe(5)
-    expect(circularArray).toStrictEqual(new CircularArray(100, 1, 2, 3, 4, 5))
-  })
-
-  it('Verify that circular array splice works as intended', () => {
-    let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
-    let deletedItems = circularArray.splice(2)
-    expect(deletedItems).toStrictEqual(new CircularArray(3, 3, 4, 5))
-    expect(circularArray.length).toBe(2)
-    expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2))
-    circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
-    deletedItems = circularArray.splice(2, 1)
-    expect(deletedItems).toStrictEqual(new CircularArray(1, 3))
-    expect(circularArray.length).toBe(4)
-    expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2, 4, 5))
-    circularArray = new CircularArray(4, 1, 2, 3, 4)
-    deletedItems = circularArray.splice(2, 1, 5, 6)
-    expect(deletedItems).toStrictEqual(new CircularArray(2, 3, 1))
-    expect(circularArray.length).toBe(4)
-    expect(circularArray).toStrictEqual(new CircularArray(4, 2, 5, 6, 4))
-  })
-
-  it('Verify that circular array concat works as intended', () => {
-    let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    circularArray = circularArray.concat(6, 7)
-    expect(circularArray.length).toBe(5)
-    expect(circularArray).toStrictEqual(new CircularArray(5, 3, 4, 5, 6, 7))
-    circularArray = new CircularArray(1)
-    circularArray = circularArray.concat(6, 7)
-    expect(circularArray.length).toBe(1)
-    expect(circularArray).toStrictEqual(new CircularArray(1, 7))
-  })
-
-  it('Verify that circular array unshift works as intended', () => {
-    let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    let arrayLength = circularArray.unshift(6, 7)
-    expect(arrayLength).toBe(5)
-    expect(circularArray.length).toBe(5)
-    expect(circularArray).toStrictEqual(new CircularArray(5, 6, 7, 1, 2, 3))
-    circularArray = new CircularArray(1)
-    arrayLength = circularArray.unshift(6, 7)
-    expect(arrayLength).toBe(1)
-    expect(circularArray.length).toBe(1)
-    expect(circularArray).toStrictEqual(new CircularArray(1, 6))
-  })
-
-  it('Verify that circular array resize works as intended', () => {
-    expect(() => new CircularArray().resize(0.25)).toThrow(
-      new TypeError('Invalid circular array size: 0.25 is not a safe integer')
-    )
-    expect(() => new CircularArray().resize(-1)).toThrow(
-      new RangeError('Invalid circular array size: -1 < 0')
-    )
-    expect(() =>
-      new CircularArray().resize(Number.MAX_SAFE_INTEGER + 1)
-    ).toThrow(
-      new TypeError(
-        `Invalid circular array size: ${
-          Number.MAX_SAFE_INTEGER + 1
-        } is not a safe integer`
-      )
-    )
-    let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    circularArray.resize(0)
-    expect(circularArray.size).toBe(0)
-    expect(circularArray).toStrictEqual(new CircularArray(0))
-    circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    circularArray.resize(1)
-    expect(circularArray.size).toBe(1)
-    expect(circularArray).toStrictEqual(new CircularArray(1, 1))
-    circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    circularArray.resize(3)
-    expect(circularArray.size).toBe(3)
-    expect(circularArray).toStrictEqual(new CircularArray(3, 1, 2, 3))
-    circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
-    circularArray.resize(8)
-    expect(circularArray.size).toBe(8)
-    expect(circularArray).toStrictEqual(new CircularArray(8, 1, 2, 3, 4, 5))
-  })
-})
diff --git a/tests/circular-buffer.test.mjs b/tests/circular-buffer.test.mjs
new file mode 100644 (file)
index 0000000..ec86ca2
--- /dev/null
@@ -0,0 +1,60 @@
+import { expect } from 'expect'
+
+import { CircularBuffer, defaultBufferSize } from '../lib/circular-buffer.cjs'
+
+describe('Circular buffer test suite', t => {
+  it('Verify that circular buffer can be instantiated', () => {
+    const circularBuffer = new CircularBuffer()
+    expect(circularBuffer).toBeInstanceOf(CircularBuffer)
+    expect(circularBuffer.readIdx).toBe(0)
+    expect(circularBuffer.writeIdx).toBe(0)
+    expect(circularBuffer.maxArrayIdx).toBe(defaultBufferSize - 1)
+    expect(circularBuffer.items).toBeInstanceOf(Array)
+    expect(circularBuffer.items.length).toBe(defaultBufferSize)
+  })
+
+  it('Verify that circular buffer size can be set at instance creation', () => {
+    const circularBuffer = new CircularBuffer(1000)
+    expect(circularBuffer.maxArrayIdx).toBe(999)
+    expect(circularBuffer.items).toBeInstanceOf(Array)
+    expect(circularBuffer.items.length).toBe(1000)
+  })
+
+  it('Verify that circular buffer size is valid at instance creation', () => {
+    expect(() => new CircularBuffer(0.25)).toThrow(
+      new TypeError('Invalid circular buffer size: 0.25 is not an integer')
+    )
+    expect(() => new CircularBuffer(-1)).toThrow(
+      new RangeError('Invalid circular buffer size: -1 < 0')
+    )
+    expect(() => new CircularBuffer(Number.MAX_SAFE_INTEGER + 1)).toThrow(
+      new TypeError(
+        `Invalid circular buffer size: ${
+          Number.MAX_SAFE_INTEGER + 1
+        } is not an integer`
+      )
+    )
+  })
+
+  it('Verify that circular buffer put() works as intended', () => {
+    const circularBuffer = new CircularBuffer(4)
+    circularBuffer.put(1)
+    expect(circularBuffer.items).toMatchObject([1])
+    expect(circularBuffer.writeIdx).toBe(1)
+    circularBuffer.put(2)
+    expect(circularBuffer.items).toMatchObject([1, 2])
+    expect(circularBuffer.writeIdx).toBe(2)
+    circularBuffer.put(3)
+    expect(circularBuffer.items).toMatchObject([1, 2, 3])
+    expect(circularBuffer.writeIdx).toBe(3)
+    circularBuffer.put(4)
+    expect(circularBuffer.items).toMatchObject([1, 2, 3, 4])
+    expect(circularBuffer.writeIdx).toBe(0)
+    circularBuffer.put(5)
+    expect(circularBuffer.items).toMatchObject([5, 2, 3, 4])
+    expect(circularBuffer.writeIdx).toBe(1)
+    circularBuffer.put(6)
+    expect(circularBuffer.items).toMatchObject([5, 6, 3, 4])
+    expect(circularBuffer.writeIdx).toBe(2)
+  })
+})
index 441e7ffc80eb5a8a9408ceb55664a0cc5c77a4f6..0c91349765f65c80884d4c50d8b45d93424e37fd 100644 (file)
@@ -8,7 +8,7 @@ import { fileURLToPath } from 'node:url'
 import { expect } from 'expect'
 import { restore, stub } from 'sinon'
 
-import { CircularArray } from '../../lib/circular-array.cjs'
+import { CircularBuffer } from '../../lib/circular-buffer.cjs'
 import {
   DynamicClusterPool,
   DynamicThreadPool,
@@ -761,17 +761,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -933,17 +933,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -961,17 +961,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -1003,17 +1003,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -1021,10 +1021,6 @@ describe('Abstract pool test suite', () => {
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         numberOfWorkers * maxMultiplier
       )
-      expect(workerNode.usage.runTime.history.length).toBe(0)
-      expect(workerNode.usage.waitTime.history.length).toBe(0)
-      expect(workerNode.usage.elu.idle.history.length).toBe(0)
-      expect(workerNode.usage.elu.active.history.length).toBe(0)
     }
     pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
     for (const workerNode of pool.workerNodes) {
@@ -1039,17 +1035,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -1057,10 +1053,6 @@ describe('Abstract pool test suite', () => {
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         numberOfWorkers * maxMultiplier
       )
-      expect(workerNode.usage.runTime.history.length).toBe(0)
-      expect(workerNode.usage.waitTime.history.length).toBe(0)
-      expect(workerNode.usage.elu.idle.history.length).toBe(0)
-      expect(workerNode.usage.elu.active.history.length).toBe(0)
     }
     await pool.destroy()
   })
@@ -1452,17 +1444,17 @@ describe('Abstract pool test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1683,17 +1675,17 @@ describe('Abstract pool test suite', () => {
             stolen: 0
           },
           runTime: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           waitTime: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           elu: {
             idle: {
-              history: expect.any(CircularArray)
+              history: expect.any(CircularBuffer)
             },
             active: {
-              history: expect.any(CircularArray)
+              history: expect.any(CircularBuffer)
             }
           }
         })
@@ -1752,17 +1744,17 @@ describe('Abstract pool test suite', () => {
             stolen: 0
           },
           runTime: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           waitTime: {
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           },
           elu: {
             idle: {
-              history: expect.any(CircularArray)
+              history: expect.any(CircularBuffer)
             },
             active: {
-              history: expect.any(CircularArray)
+              history: expect.any(CircularBuffer)
             }
           }
         })
index e4d1dd07ece0a5aeb8702a31c5386eb45d468ae0..3f2f2e81cf5b41bb4122adbda737b9b086ebd511 100644 (file)
@@ -2,7 +2,7 @@ import { randomInt } from 'node:crypto'
 
 import { expect } from 'expect'
 
-import { CircularArray } from '../../../lib/circular-array.cjs'
+import { CircularBuffer } from '../../../lib/circular-buffer.cjs'
 import {
   DynamicClusterPool,
   DynamicThreadPool,
@@ -258,17 +258,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -314,17 +314,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -532,17 +532,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -591,17 +591,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -731,17 +731,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -800,17 +800,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -950,17 +950,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1025,17 +1025,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         waitTime: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1181,17 +1181,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1277,17 +1277,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1378,17 +1378,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: expect.objectContaining({
           idle: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           }),
           active: expect.objectContaining({
-            history: expect.any(CircularArray)
+            history: expect.any(CircularBuffer)
           })
         })
       })
@@ -1589,17 +1589,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -1673,17 +1673,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -1762,17 +1762,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -2000,17 +2000,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
@@ -2104,17 +2104,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         waitTime: expect.objectContaining({
-          history: expect.any(CircularArray)
+          history: expect.any(CircularBuffer)
         }),
         elu: {
           idle: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           },
           active: {
-            history: new CircularArray()
+            history: expect.any(CircularBuffer)
           }
         }
       })
index 3842c8c5e223e3e89fdea92e581b0d7f8e41fb52..3d9634ff50256ea0cac40b80351ba688a5c66a64 100644 (file)
@@ -3,10 +3,7 @@ import { Worker as ThreadWorker } from 'node:worker_threads'
 
 import { expect } from 'expect'
 
-import {
-  CircularArray,
-  DEFAULT_CIRCULAR_ARRAY_SIZE
-} from '../../lib/circular-array.cjs'
+import { CircularBuffer } from '../../lib/circular-buffer.cjs'
 import { WorkerTypes } from '../../lib/index.cjs'
 import {
   createWorker,
@@ -16,6 +13,7 @@ import {
   getWorkerType,
   updateMeasurementStatistics
 } from '../../lib/pools/utils.cjs'
+import { MeasurementHistorySize } from '../../lib/pools/worker.cjs'
 
 describe('Pool utils test suite', () => {
   it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => {
@@ -38,8 +36,9 @@ describe('Pool utils test suite', () => {
   })
 
   it('Verify updateMeasurementStatistics() behavior', () => {
+    const circularBuffer = new CircularBuffer(MeasurementHistorySize)
     const measurementStatistics = {
-      history: new CircularArray()
+      history: circularBuffer
     }
     updateMeasurementStatistics(
       measurementStatistics,
@@ -50,7 +49,7 @@ describe('Pool utils test suite', () => {
       aggregate: 0.01,
       maximum: 0.01,
       minimum: 0.01,
-      history: new CircularArray()
+      history: circularBuffer
     })
     updateMeasurementStatistics(
       measurementStatistics,
@@ -61,7 +60,7 @@ describe('Pool utils test suite', () => {
       aggregate: 0.03,
       maximum: 0.02,
       minimum: 0.01,
-      history: new CircularArray()
+      history: circularBuffer
     })
     updateMeasurementStatistics(
       measurementStatistics,
@@ -73,7 +72,7 @@ describe('Pool utils test suite', () => {
       maximum: 0.02,
       minimum: 0.001,
       average: 0.001,
-      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
+      history: circularBuffer
     })
     updateMeasurementStatistics(
       measurementStatistics,
@@ -85,7 +84,7 @@ describe('Pool utils test suite', () => {
       maximum: 0.02,
       minimum: 0.001,
       average: 0.002,
-      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
+      history: circularBuffer
     })
     updateMeasurementStatistics(
       measurementStatistics,
@@ -97,12 +96,7 @@ describe('Pool utils test suite', () => {
       maximum: 0.02,
       minimum: 0.001,
       median: 0.003,
-      history: new CircularArray(
-        DEFAULT_CIRCULAR_ARRAY_SIZE,
-        0.001,
-        0.003,
-        0.006
-      )
+      history: circularBuffer
     })
     updateMeasurementStatistics(
       measurementStatistics,
@@ -114,13 +108,7 @@ describe('Pool utils test suite', () => {
       maximum: 0.02,
       minimum: 0.001,
       average: 0.005,
-      history: new CircularArray(
-        DEFAULT_CIRCULAR_ARRAY_SIZE,
-        0.001,
-        0.003,
-        0.006,
-        0.01
-      )
+      history: circularBuffer
     })
   })
 
index c4f84a51ada0e831b3b2f5dd1a222fffc898c5db..54a69ca458a8566067c2c8af8160e6605214a6cf 100644 (file)
@@ -3,7 +3,7 @@ import { MessageChannel, Worker as ThreadWorker } from 'node:worker_threads'
 
 import { expect } from 'expect'
 
-import { CircularArray } from '../../lib/circular-array.cjs'
+import { CircularBuffer } from '../../lib/circular-buffer.cjs'
 import { WorkerTypes } from '../../lib/index.cjs'
 import { WorkerNode } from '../../lib/pools/worker-node.cjs'
 import { PriorityQueue } from '../../lib/priority-queue.cjs'
@@ -206,17 +206,17 @@ describe('Worker node test suite', () => {
         failed: 0
       },
       runTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       waitTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       elu: {
         idle: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         active: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         }
       }
     })
@@ -252,17 +252,17 @@ describe('Worker node test suite', () => {
         failed: 0
       },
       runTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       waitTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       elu: {
         idle: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         active: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         }
       }
     })
@@ -314,17 +314,17 @@ describe('Worker node test suite', () => {
         failed: 0
       },
       runTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       waitTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       elu: {
         idle: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         active: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         }
       }
     })
@@ -338,17 +338,17 @@ describe('Worker node test suite', () => {
         failed: 0
       },
       runTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       waitTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       elu: {
         idle: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         active: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         }
       }
     })
@@ -362,17 +362,17 @@ describe('Worker node test suite', () => {
         failed: 0
       },
       runTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       waitTime: {
-        history: new CircularArray()
+        history: expect.any(CircularBuffer)
       },
       elu: {
         idle: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         },
         active: {
-          history: new CircularArray()
+          history: expect.any(CircularBuffer)
         }
       }
     })