Skip to content

perf_hooks.performance.timerify() with histogram: RangeError [ERR_OUT_OF_RANGE] on arm64 #41641

Open
@jonahsnider

Description

@jonahsnider

Version

v14, v16, v17, v18

Platform

macOS v12.4 (21F79).

Darwin 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 arm64

Subsystem

perf_hooks

What steps will reproduce the bug?

Run this snippet:

import {createHistogram, performance} from 'node:perf_hooks';

const fn = () => {};

const timerified = performance.timerify(fn, {histogram: createHistogram()});

for (let i = 0; i < 100_000; i++) {
	try {
		timerified();
	} catch (error) {
		console.error('Crashed on iteration', i);

		throw error;
	}
}

How often does it reproduce? Is there a required condition?

100% consistent reproduction, requires arm64, maybe requires macOS.

What is the expected behavior?

Calling the timerified function returned from perf_hooks.performance.timerify() should successfully record to the histogram.

What do you see instead?

node:internal/errors:466
    ErrorCaptureStackTrace(err);
    ^

RangeError [ERR_OUT_OF_RANGE]: The value of "val" is out of range. It must be a safe integer greater than 0. Received 0
    at new NodeError (node:internal/errors:377:5)
    at RecordableHistogram.record (node:internal/histogram:290:13)
    at processComplete (node:internal/perf/timerify:40:15)
    at timerified fn (node:internal/perf/timerify:88:5)
    at file:///Users/jonah/programming/benchmark/index.mjs:9:3
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:409:24)
    at async loadESM (node:internal/process/esm_loader:85:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12) {
  code: 'ERR_OUT_OF_RANGE'
}

Node.js v18.1.0

Additional information

Originally reported here: sindresorhus/yoctocolors#9 (comment)


The bug appears to be from the implementation of perf_hooks.performance.timerify() with a histogram, when calling the returned timerified function. The error comes from the input validation of RecordableHistogram#record(), attempting to record a value x < 1 will throw. For whatever reason timerify() seems to be recording an execution duration of 0 and trying to record that. See the error stacktrace for more info.

Metadata

Metadata

Assignees

No one assigned

    Labels

    perf_hooksIssues and PRs related to the implementation of the Performance Timing API.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions