fix: workaround import issue with `node:os` module in node 16.x.x
[poolifier.git] / src / utils.ts
CommitLineData
aa4bf4b2 1import * as os from 'node:os'
3c93feb9
JB
2import type {
3 MeasurementStatisticsRequirements,
4 WorkerChoiceStrategyOptions
5} from './pools/selection-strategies/selection-strategies-types'
59317253 6import type { KillBehavior } from './worker/worker-options'
bbeadd16 7
6e9d10db
JB
8/**
9 * An intentional empty function.
10 */
4f3c3d89 11export const EMPTY_FUNCTION: () => void = Object.freeze(() => {
6e9d10db 12 /* Intentionally empty */
4f3c3d89 13})
78099a15
JB
14
15/**
bbeadd16
JB
16 * Default worker choice strategy options.
17 */
18export const DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS: WorkerChoiceStrategyOptions =
19 {
932fc8be 20 runTime: { median: false },
5df69fab
JB
21 waitTime: { median: false },
22 elu: { median: false }
bbeadd16
JB
23 }
24
3c93feb9
JB
25/**
26 * Default measurement statistics requirements.
27 */
28export const DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS: MeasurementStatisticsRequirements =
29 {
30 aggregate: false,
31 average: false,
32 median: false
33 }
34
51474716 35/**
ab80dc46
JB
36 * Returns safe host OS optimized estimate of the default amount of parallelism a pool should use.
37 * Always returns a value greater than zero.
38 *
39 * @returns The host OS optimized maximum pool size.
51474716
JB
40 */
41export const availableParallelism = (): number => {
42 let availableParallelism = 1
43 try {
aa4bf4b2 44 availableParallelism = os.availableParallelism()
51474716 45 } catch {
aa4bf4b2 46 const numberOfCpus = os.cpus()
2845f2a5
JB
47 if (Array.isArray(numberOfCpus) && numberOfCpus.length > 0) {
48 availableParallelism = numberOfCpus.length
51474716
JB
49 }
50 }
51 return availableParallelism
52}
53
bbeadd16 54/**
afe0d5bf 55 * Computes the median of the given data set.
78099a15
JB
56 *
57 * @param dataSet - Data set.
58 * @returns The median of the given data set.
59 */
60export const median = (dataSet: number[]): number => {
4a45e8d2
JB
61 if (Array.isArray(dataSet) && dataSet.length === 0) {
62 return 0
63 }
78099a15
JB
64 if (Array.isArray(dataSet) && dataSet.length === 1) {
65 return dataSet[0]
66 }
c6f42dd6
JB
67 const sortedDataSet = dataSet.slice().sort((a, b) => a - b)
68 return (
69 (sortedDataSet[(sortedDataSet.length - 1) >> 1] +
70 sortedDataSet[sortedDataSet.length >> 1]) /
71 2
72 )
78099a15 73}
0d80593b 74
afe0d5bf
JB
75/**
76 * Rounds the given number to the given scale.
64383951 77 * The rounding is done using the "round half away from zero" method.
afe0d5bf
JB
78 *
79 * @param num - The number to round.
80 * @param scale - The scale to round to.
81 * @returns The rounded number.
82 */
83export const round = (num: number, scale = 2): number => {
84 const rounder = Math.pow(10, scale)
85 return Math.round(num * rounder * (1 + Number.EPSILON)) / rounder
86}
87
3c653a03
JB
88/**
89 * Is the given object a plain object?
90 *
91 * @param obj - The object to check.
92 * @returns `true` if the given object is a plain object, `false` otherwise.
93 */
0d80593b
JB
94export const isPlainObject = (obj: unknown): boolean =>
95 typeof obj === 'object' &&
96 obj !== null &&
97 obj?.constructor === Object &&
98 Object.prototype.toString.call(obj) === '[object Object]'
59317253
JB
99
100/**
101 * Detects whether the given value is a kill behavior or not.
102 *
103 * @typeParam KB - Which specific KillBehavior type to test against.
104 * @param killBehavior - Which kind of kill behavior to detect.
105 * @param value - Any value.
106 * @returns `true` if `value` was strictly equals to `killBehavior`, otherwise `false`.
107 */
108export const isKillBehavior = <KB extends KillBehavior>(
109 killBehavior: KB,
110 value: unknown
111): value is KB => {
112 return value === killBehavior
113}
49d1b48c
JB
114
115/**
116 * Detects whether the given value is an asynchronous function or not.
117 *
118 * @param fn - Any value.
119 * @returns `true` if `fn` was an asynchronous function, otherwise `false`.
120 */
121export const isAsyncFunction = (
122 fn: unknown
123): fn is (...args: unknown[]) => Promise<unknown> => {
124 return typeof fn === 'function' && fn.constructor.name === 'AsyncFunction'
125}