Skip to content

Commit bcebead

Browse files
committed
fix(utils): make mToNsBigint tolerate fractional milliseconds
`mToNsBigint` did `BigInt(ms) * 1_000_000n`, which throws "RangeError: ... not an integer" for a fractional `ms`. This is reachable via `new Bench({ concurrency: 'task', time })` with a non-integer `time` / `warmupTime` on the hrtime provider (Node's default): `withConcurrency` calls `fromMs(time)` and the task silently ends up in `state: 'errored'`. Round to the nearest nanosecond with `BigInt(Math.round(ms * 1e6))` — identical for integer ms, no longer throwing on fractional ms. Add a regression test. Also document that the exported `hrtimeNow` narrows the absolute timestamp to a number (lossy past ~104 days of uptime); prefer `hrtimeNowTimestampProvider`.
1 parent e3acdab commit bcebead

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

src/utils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export const nBigintToMs = (ns: bigint) => Number(ns) / 1e6
151151
* @param ms - milliseconds
152152
* @returns nanoseconds as bigint
153153
*/
154-
export const mToNsBigint = (ms: number) => BigInt(ms) * 1_000_000n
154+
export const mToNsBigint = (ms: number) => BigInt(Math.round(ms * 1e6))
155155

156156
/**
157157
* Formats a number with the specified significant digits and maximum fraction digits.
@@ -906,6 +906,11 @@ const hrtimeBigint =
906906

907907
/**
908908
* Returns the current timestamp in milliseconds using `process.hrtime.bigint()`.
909+
*
910+
* Narrows the absolute nanosecond value to a `number`, which loses precision
911+
* once it exceeds `Number.MAX_SAFE_INTEGER` (~104 days of uptime). For
912+
* benchmarking prefer `hrtimeNowTimestampProvider`, which keeps the bigint
913+
* until after the delta is taken.
909914
* @returns the current timestamp in milliseconds
910915
*/
911916
export const hrtimeNow = () => nToMs(Number(hrtimeBigint()))

test/utils-ms-to-n.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import { expect, test } from 'vitest'
22

3-
import { mToNs } from '../src/utils'
3+
import { mToNs, mToNsBigint } from '../src/utils'
44

55
test('mToNs', () => {
66
expect(mToNs(1)).toBe(1000000)
77
expect(mToNs(0.000001)).toBe(1)
88
expect(mToNs(1234.56789)).toBe(1234567890)
99
expect(mToNs(-1)).toBe(-1000000)
1010
})
11+
12+
test('mToNsBigint', () => {
13+
expect(mToNsBigint(1)).toBe(1000000n)
14+
expect(mToNsBigint(1000)).toBe(1000000000n)
15+
expect(mToNsBigint(100.5)).toBe(100500000n)
16+
expect(mToNsBigint(1234.56789)).toBe(1234567890n)
17+
})

0 commit comments

Comments
 (0)