Repository navigation
Description
Version
v18.14.2
Platform
Linux qubit 5.15.108-0-lts #1-Alpine SMP Fri, 21 Apr 2023 05:55:14 +0000 x86_64 GNU/Linux
Subsystem
perf_hooks
What steps will reproduce the bug?
In an interactive node session run:
function timeDelta() {
// The delta should be approximately the same on each invocation (assuming the system time is unchanged).
return Date.now() - performance.now();
};
const ref = timeDelta();
const before = timeDelta();Now suspend and resume the machine / VM through whatever means. Then continue in the same node session:
const after = timeDelta();
console.log('BEFORE:', ref - before, 'AFTER:', ref - after);Observe that the after value is incorrectly missing a number of seconds that matches the time the system was suspended. Eg. from my run:
BEFORE: -0.410888671875
AFTER: -7346.271728515625
How often does it reproduce? Is there a required condition?
100% (on Linux)
What is the expected behavior? Why is that the expected behavior?
performance.now() is expected to jump with the realtime passed time while suspended according to the spec and w3c/hr-time#115.
The mdn/content#4713 issue also goes into detail on how the "Ticking During Sleep" applies to various platforms.
What do you see instead?
No jump during sleep. Eg. by using more suitable clock reference, as proposed implemented in libuv/libuv#1674.
Additional information
The current performance.now() implementation is based on process.hrtime():
node/lib/internal/perf/utils.js
Lines 13 to 16 in 2ac5e98
| function now() { | |
| const hr = process.hrtime(); | |
| return (hr[0] * 1000 + hr[1] / 1e6) - timeOrigin; | |
| } |
This issue also seems to contain a lot of relevant context around a concrete problem: open-telemetry/opentelemetry-js#852.
Activity
tniessen commentedon Apr 26, 2023
Are you referring to this part of the spec?
After skimming through the spec, w3c/hr-time#115, open-telemetry/opentelemetry-js#852, and mdn/content#4713, I am not quite sure how to interpret this for non-browsers.
bnoordhuis commentedon Apr 26, 2023
You could perhaps argue it's a quality-of-implementation issue but it doesn't look like a spec conformance issue to me.
The spec says the clock source should be monotonic. The only guarantee with monotonic clocks is that they don't jump back in time but that's all.
Aside: Date.now() - what you use in your example - is based on a real-time clock, not a monotonic clock. Real-time clocks can jump forward and backward in time.
kanongil commentedon Apr 27, 2023
Yes.
kanongil commentedon Apr 27, 2023
@bnoordhuis Yeah, the expected suspend behaviour is poorly worded as described in w3c/hr-time#115.
The main reason I bring this up, is that I would like a timer with that quality, and I expect that the current behaviour can cause subtle issues, especially on mobile. I have previously had to investigate and workaround this issue in JS code running on buggy Browsers.
It is also possible that the current behaviour is different across the supported platforms, notably for Windows.
Also, the
Date.now()usage in the example is just to demonstrate the issue, and I explicitly caveat that it only works if the system time is unmodified during the test.kanongil commentedon Apr 27, 2023
The spec also states regarding clocks that they:
This is not currently the case after a suspend.
[-]performance.now() is not web compatible[/-][+]performance.now() should jump after sleep/suspend/hibernation[/+]bnoordhuis commentedon Apr 29, 2023
Not all platforms have easily accessible adjusted-for-suspend clock sources so this may take a while to materialize, if ever.
github-actions commentedon Jun 2, 2026
This issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
kanongil commentedon Jun 3, 2026
Still an issue, at least on Linux.
A monotonic realtime clock was added with
uv_clock_gettime()in libuv/libuv#3971, but it is still unused in node.The current
performance.now()implementation is here:node/src/node_perf.cc
Lines 309 to 312 in b345a17
github-actions commentedon Sep 3, 2026
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
github-actions commentedon Oct 4, 2026
This issue has been automatically closed after 30 days of inactivity following its stale status (no activity for a total of 120 days).
If this is still relevant, feel free to reopen it or leave a comment with additional details so we can continue the discussion.