fix: readd cpu speed computation but only if necessary
[poolifier.git] / src / pools / utils.ts
index ff2709826076459a8ef4ee417221b333b3ca70e3..724c4ab960c691e8f4a5d8661f9c442ff14d5b3d 100644 (file)
@@ -1,22 +1,23 @@
-import { existsSync } from 'node:fs'
 import cluster, { Worker as ClusterWorker } from 'node:cluster'
+import { existsSync } from 'node:fs'
+import { cpus } from 'node:os'
+import { env } from 'node:process'
 import {
   SHARE_ENV,
   Worker as ThreadWorker,
   type WorkerOptions
 } from 'node:worker_threads'
-import { env } from 'node:process'
-import { randomInt } from 'node:crypto'
-import { cpus } from 'node:os'
-import { average, isPlainObject, max, median, min } from '../utils.js'
+
 import type { MessageValue, Task } from '../utility-types.js'
+import { average, isPlainObject, max, median, min } from '../utils.js'
+import type { IPool, TasksQueueOptions } from './pool.js'
 import {
   type MeasurementStatisticsRequirements,
   WorkerChoiceStrategies,
   type WorkerChoiceStrategy,
   type WorkerChoiceStrategyOptions
 } from './selection-strategies/selection-strategies-types.js'
-import type { IPool, TasksQueueOptions } from './pool.js'
+import type { WorkerChoiceStrategyContext } from './selection-strategies/worker-choice-strategy-context.js'
 import {
   type IWorker,
   type IWorkerNode,
@@ -26,7 +27,6 @@ import {
   WorkerTypes,
   type WorkerUsage
 } from './worker.js'
-import type { WorkerChoiceStrategyContext } from './selection-strategies/worker-choice-strategy-context.js'
 
 /**
  * Default measurement statistics requirements.
@@ -100,23 +100,39 @@ const getDefaultWeights = (
   return weights
 }
 
+const estimatedCpuSpeed = (): number => {
+  const runs = 150000000
+  const begin = performance.now()
+  // eslint-disable-next-line no-empty
+  for (let i = runs; i > 0; i--) {}
+  const end = performance.now()
+  const duration = end - begin
+  return Math.trunc(runs / duration / 1000) // in MHz
+}
+
 const getDefaultWorkerWeight = (): number => {
-  const cpuSpeed = randomInt(500, 2500)
+  const currentCpus = cpus()
+  let estCpuSpeed: number | undefined
+  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+  if (currentCpus.every(cpu => cpu.speed == null || cpu.speed === 0)) {
+    estCpuSpeed = estimatedCpuSpeed()
+  }
   let cpusCycleTimeWeight = 0
-  for (const cpu of cpus()) {
+  for (const cpu of currentCpus) {
     // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
     if (cpu.speed == null || cpu.speed === 0) {
       cpu.speed =
         // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
-        cpus().find(cpu => cpu.speed != null && cpu.speed !== 0)?.speed ??
-        cpuSpeed
+        currentCpus.find(cpu => cpu.speed != null && cpu.speed !== 0)?.speed ??
+        estCpuSpeed ??
+        2000
     }
     // 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)
+  return Math.round(cpusCycleTimeWeight / currentCpus.length)
 }
 
 export const checkFilePath = (filePath: string | undefined): void => {