nodejs / nodejs/node

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

Open
#41,641 5 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

perf_hooks
Dominant language
JavaScript
Stars
122k
Forks
37.3k
Avg merge
4d 2h
Merged PRs (30d)
283

Description

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: https://github.com/sindresorhus/yoctocolors/pull/9#issuecomment-1019033882


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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the snippet on arm64, then inspect internal/perf/timerify and internal/histogram, especially processComplete and RecordableHistogram.record as shown in the stack trace. Done means timerify() records the execution without throwing ERR_OUT_OF_RANGE and the behavior is covered by an appropriate regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
backend, performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.