From 298bd124a2f094e321d2426a48af75b689d9bb6d Mon Sep 17 00:00:00 2001 From: ehmicky Date: Sun, 25 Aug 2019 17:39:21 +0200 Subject: [PATCH] Use time-resolution --- package-lock.json | 9 ++++ package.json | 1 + src/resolution.js | 73 -------------------------- src/run/runners/node/benchmark/bias.js | 5 +- 4 files changed, 13 insertions(+), 75 deletions(-) delete mode 100644 src/resolution.js diff --git a/package-lock.json b/package-lock.json index 38e2167be..b29810dde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11847,6 +11847,15 @@ "xtend": "~4.0.0" } }, + "time-resolution": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/time-resolution/-/time-resolution-0.1.1.tgz", + "integrity": "sha512-UnxHylIzHKuO2a4wnPHkTvAUq4vrUhLF9xroG62J6Qvk26ibKkU9LEt23cw9q2eEbZ+YP0+C4AtNORFw94nxOg==", + "requires": { + "core-js": "^3.2.1", + "precise-now": "^0.1.1" + } + }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", diff --git a/package.json b/package.json index c884c12fd..a15a4ea16 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "slugify": "^1.3.4", "string-width": "^4.1.0", "strip-ansi": "^5.2.0", + "time-resolution": "^0.1.1", "uuid": "^3.3.3", "write-file-atomic": "^3.0.0", "yargs": "^14.0.0", diff --git a/src/resolution.js b/src/resolution.js deleted file mode 100644 index d99f50544..000000000 --- a/src/resolution.js +++ /dev/null @@ -1,73 +0,0 @@ -import now from 'precise-now' - -// Retrieve system's time resolution in nanoseconds. -// If the resolution is <1ns, returns 1ns. -// Time resolution depends on a combination of hardware and software factors. -export const getTimeResolution = function() { - const times = getTimes(REPEAT) - return POSSIBLE_RESOLUTIONS.find(resolution => - isTimeResolution(resolution, times), - ) -} - -// Run `now()` several times in a row. -// We do it several times because there is a chance that the next resolution -// would be hit otherwise. For example: -// - if resolution is 1ns, samples might (by chance) all be modulo 5ns -// - if resolution is 5ns, samples might (by chance) all be modulo 10ns -// The probability for this to happen is: -// - if resolution is *1ns, `1 / 5 ** length` -// - if resolution is *5ns, `1 / 2 ** length` -// So with `length` `100`, we get this error only once every `1e30` calls. -// We must use imperative code because the loop size is unknown. -/* eslint-disable fp/no-let, fp/no-loops, fp/no-mutation, fp/no-mutating-methods, -max-depth */ -const getTimes = function(length) { - const times = [] - let lastTime = 0 - - while (times.length < length) { - const time = now() - - // If the resolution is very low, we need to perform `now()` several times - // until the result changes - if (time !== lastTime) { - lastTime = time - times.push(time) - } - } - - return times -} -/* eslint-enable fp/no-let, fp/no-loops, fp/no-mutation, fp/no-mutating-methods, -max-depth */ - -const REPEAT = 1e2 - -// Check among all `now()` if they fit a specific time resolution -const isTimeResolution = function(resolution, times) { - return times.every(time => time % resolution === 0) -} - -// Available time resolutions from 50ms, 10ms, 5ms, ... to 1ns. -// In nanoseconds. -const getPossibleResolutions = function() { - return Array.from({ length: MAX_RESOLUTION_EXPONENT }, getExponent).flatMap( - getPossibleResolution, - ) -} - -// 8 digits after nanoseconds, i.e. 99ms-10ms -const MAX_RESOLUTION_EXPONENT = 8 - -const getExponent = function(value, index) { - return MAX_RESOLUTION_EXPONENT - index - 1 -} - -const getPossibleResolution = function(exponent) { - const scale = 10 ** exponent - // eslint-disable-next-line no-magic-numbers - return [5 * scale, scale] -} - -const POSSIBLE_RESOLUTIONS = getPossibleResolutions() diff --git a/src/run/runners/node/benchmark/bias.js b/src/run/runners/node/benchmark/bias.js index f42ce9a45..db65e823c 100644 --- a/src/run/runners/node/benchmark/bias.js +++ b/src/run/runners/node/benchmark/bias.js @@ -1,4 +1,5 @@ -import { getTimeResolution } from '../../../../resolution.js' +import timeResolution from 'time-resolution' + import { getMedian } from '../../../../stats/methods.js' import { benchmarkLoop } from './loop.js' @@ -58,7 +59,7 @@ const getMinTime = function(nowBias) { return Math.max(minPrecisionTime, minNowBiasTime) } -const TIME_RESOLUTION = getTimeResolution() +const TIME_RESOLUTION = timeResolution() // The task loop must be at least `MIN_PRECISION` slower than time resolution const MIN_PRECISION = 1e2 // The task loop must be at least `MIN_NOW_BIAS` slower than `nowBias`