'fp',
'fs',
'func',
+ 'idx',
'inheritDoc',
'javascript',
'jsdoc',
"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",
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
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==}
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:
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'}
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'}
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'}
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'}
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==}
colorette@2.0.20: {}
- commander@11.1.0: {}
+ commander@12.1.0: {}
commander@2.20.3: {}
'@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: {}
'@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
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
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: {}
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:
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: {}
picomatch@2.3.1: {}
+ picomatch@4.0.2: {}
+
pidtree@0.6.0: {}
possible-typed-array-names@1.0.0: {}
y18n@5.0.8: {}
- yaml@2.3.4: {}
+ yaml@2.4.2: {}
yargs-parser@20.2.4: {}
+++ /dev/null
-// 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`)
- }
- }
-}
--- /dev/null
+/**
+ * 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`)
+ }
+ }
+}
-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'
average(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.runTime.history),
+ accumulator.concat(
+ workerNode.usage.runTime.history.toArray()
+ ),
[]
)
)
median(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.runTime.history),
+ accumulator.concat(
+ workerNode.usage.runTime.history.toArray()
+ ),
[]
)
)
average(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.waitTime.history),
+ accumulator.concat(
+ workerNode.usage.waitTime.history.toArray()
+ ),
[]
)
)
median(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.waitTime.history),
+ accumulator.concat(
+ workerNode.usage.waitTime.history.toArray()
+ ),
[]
)
)
average(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.elu.idle.history),
+ accumulator.concat(
+ workerNode.usage.elu.idle.history.toArray()
+ ),
[]
)
)
median(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.elu.idle.history),
+ accumulator.concat(
+ workerNode.usage.elu.idle.history.toArray()
+ ),
[]
)
)
average(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.elu.active.history),
+ accumulator.concat(
+ workerNode.usage.elu.active.history.toArray()
+ ),
[]
)
)
median(
this.workerNodes.reduce<number[]>(
(accumulator, workerNode) =>
- accumulator.concat(workerNode.usage.elu.active.history),
+ accumulator.concat(
+ workerNode.usage.elu.active.history.toArray()
+ ),
[]
)
)
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
}
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'
type EventHandler,
type IWorker,
type IWorkerNode,
+ MeasurementHistorySize,
type StrategyData,
type WorkerInfo,
type WorkerNodeOptions,
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)
}
}
}
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)
}
}
}
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'
/**
| ErrorHandler<Worker>
| ExitHandler<Worker>
+/**
+ * Measurement history size.
+ */
+export const MeasurementHistorySize = 386
+
/**
* Measurement statistics.
*
/**
* Measurement history.
*/
- readonly history: CircularArray<number>
+ readonly history: CircularBuffer<number>
}
/**
+++ /dev/null
-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))
- })
-})
--- /dev/null
+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)
+ })
+})
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,
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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) {
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)
}
}
})
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()
})
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)
})
})
})
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)
}
}
})
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)
}
}
})
import { expect } from 'expect'
-import { CircularArray } from '../../../lib/circular-array.cjs'
+import { CircularBuffer } from '../../../lib/circular-buffer.cjs'
import {
DynamicClusterPool,
DynamicThreadPool,
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
})
})
})
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)
})
})
})
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)
})
})
})
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)
})
})
})
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)
})
})
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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,
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', () => {
})
it('Verify updateMeasurementStatistics() behavior', () => {
+ const circularBuffer = new CircularBuffer(MeasurementHistorySize)
const measurementStatistics = {
- history: new CircularArray()
+ history: circularBuffer
}
updateMeasurementStatistics(
measurementStatistics,
aggregate: 0.01,
maximum: 0.01,
minimum: 0.01,
- history: new CircularArray()
+ history: circularBuffer
})
updateMeasurementStatistics(
measurementStatistics,
aggregate: 0.03,
maximum: 0.02,
minimum: 0.01,
- history: new CircularArray()
+ history: circularBuffer
})
updateMeasurementStatistics(
measurementStatistics,
maximum: 0.02,
minimum: 0.001,
average: 0.001,
- history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
+ history: circularBuffer
})
updateMeasurementStatistics(
measurementStatistics,
maximum: 0.02,
minimum: 0.001,
average: 0.002,
- history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
+ history: circularBuffer
})
updateMeasurementStatistics(
measurementStatistics,
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,
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
})
})
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'
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})
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)
}
}
})