X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Futils.ts;h=a7cb55f971483d12729e259110b3d872da7b5f15;hb=a4d25410764bca884efaea4d46ed9bf83b8a8dbb;hp=25233a022aac69f9db858907261ad6720e5e495e;hpb=26ce26ca8861318068427cc86697103e7a3ddbf4;p=poolifier.git diff --git a/src/utils.ts b/src/utils.ts index 25233a02..a7cb55f9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,13 +1,15 @@ import * as os from 'node:os' -import { getRandomValues } from 'node:crypto' +import { getRandomValues, randomInt } from 'node:crypto' import { Worker as ClusterWorker } from 'node:cluster' import { Worker as ThreadWorker } from 'node:worker_threads' +import { cpus } from 'node:os' import type { - InternalWorkerChoiceStrategyOptions, - MeasurementStatisticsRequirements -} from './pools/selection-strategies/selection-strategies-types' -import type { KillBehavior } from './worker/worker-options' -import { type IWorker, type WorkerType, WorkerTypes } from './pools/worker' + MeasurementStatisticsRequirements, + WorkerChoiceStrategyOptions +} from './pools/selection-strategies/selection-strategies-types.js' +import type { KillBehavior } from './worker/worker-options.js' +import { type IWorker, type WorkerType, WorkerTypes } from './pools/worker.js' +import type { IPool } from './pools/pool.js' /** * Default task name. @@ -21,23 +23,6 @@ export const EMPTY_FUNCTION: () => void = Object.freeze(() => { /* Intentionally empty */ }) -/** - * Default worker choice strategy options. - * - * @param poolMaxSize - The pool maximum size. - * @returns The default worker choice strategy options. - */ -export const getDefaultInternalWorkerChoiceStrategyOptions = ( - poolMaxSize: number -): InternalWorkerChoiceStrategyOptions => { - return { - retries: poolMaxSize, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false } - } -} - /** * Default measurement statistics requirements. */ @@ -280,3 +265,70 @@ export const once = ( return result } } + +export const getWorkerChoiceStrategyRetries = < + Worker extends IWorker, + Data, + Response +>( + pool: IPool, + opts?: WorkerChoiceStrategyOptions + ): number => { + return ( + pool.info.maxSize + + Object.keys(opts?.weights ?? getDefaultWeights(pool.info.maxSize)).length + ) +} + +const clone = (object: T): T => { + return structuredClone(object) +} + +export const buildWorkerChoiceStrategyOptions = < + Worker extends IWorker, + Data, + Response +>( + pool: IPool, + opts?: WorkerChoiceStrategyOptions + ): WorkerChoiceStrategyOptions => { + opts = clone(opts ?? {}) + opts.weights = opts?.weights ?? getDefaultWeights(pool.info.maxSize) + return { + ...{ + runTime: { median: false }, + waitTime: { median: false }, + elu: { median: false } + }, + ...opts + } +} + +const getDefaultWeights = ( + poolMaxSize: number, + defaultWorkerWeight?: number +): Record => { + defaultWorkerWeight = defaultWorkerWeight ?? getDefaultWorkerWeight() + const weights: Record = {} + for (let workerNodeKey = 0; workerNodeKey < poolMaxSize; workerNodeKey++) { + weights[workerNodeKey] = defaultWorkerWeight + } + return weights +} + +const getDefaultWorkerWeight = (): number => { + const cpuSpeed = randomInt(500, 2500) + let cpusCycleTimeWeight = 0 + for (const cpu of cpus()) { + if (cpu.speed == null || cpu.speed === 0) { + cpu.speed = + cpus().find(cpu => cpu.speed != null && cpu.speed !== 0)?.speed ?? + cpuSpeed + } + // CPU estimated cycle time + const numberOfDigits = cpu.speed.toString().length - 1 + const cpuCycleTime = 1 / (cpu.speed / Math.pow(10, numberOfDigits)) + cpusCycleTimeWeight += cpuCycleTime * Math.pow(10, numberOfDigits) + } + return Math.round(cpusCycleTimeWeight / cpus().length) +}