Repository navigation
performance.timeOrigin set incorrectly #17893
Description
Activity
- addedperf_hooksIssues and PRs related to the perf_hooks module and performance measurement APIs.Issues and PRs related to the perf_hooks module and performance measurement APIs.
on Dec 28, 2017 The ideal solution is, of course, adding such a method to libuv.
libuv/libuv#1674 - Colin was going to work on that.
@bnoordhuis Thanks for the link. In the mean time however, what do you think of having a JS workaround like the one I wrote in the OP?
If you are going to write C++ code anyway, you might as well add a wrapper for
gettimeofday()/GetSystemTimeAsFileTime()as a stop-gap measure until libuv grows the necessary APIs.I see at least two issues with the snippet you posted:
-
const next = cur + 1; while (cur !== next) cur = Date.now()busy-loops whencurjumps fromnext-1tonext+1or more, either because the process is rescheduled between statements or the system clock is changed. -
It assumes
Date.now()andprocess.hrtime()are near-instantaneous, which they usually are but not always. If the system clock is emulated (virtualized), you'll miss the mark by many microseconds, maybe by even more than a millisecond.
-
Yep. Glad you're looking at this. This was one I had been wanting to get back to but it's been lower on my priority list. Adding it libuv is definitely the best option. The wrapper that @bnoordhuis suggests is next best option.
Thanks for noticing those issues. We'll need
clock_gettime()because sub-millisecond resolution is needed for this API, and probably the Windows equivalent as well. It's quite unfortunate how slow non-vDSO timer syscalls are...gettimeofday()return microseconds andGetSystemTimeAsFileTime()returns the time in tenths of microseconds1. Is that fast enough?1 The real granularity may of course be worse.
It's quite unfortunate how slow non-vDSO timer syscalls are...
The vDSO is not exempt either. Virtualization software normally intercepts the rdtsc instruction, the most common clock source inside the vDSO.
@bnoordhuis Ah heh, I read the unit wrong. Yes, that’ll be enough. (The spec calls for at least 5-μs resolution, and if that is not possible, 1-ms resolution.)
Virtualization software normally intercepts the rdtsc instruction, the most common clock source inside the vDSO.
Is rdtsc intercepted for hardware-assisted virtualization or KVM as well?
Reacted by James M SnellFor products like VMware and VirtualBox I think the answer is "practically always."
AMD and Intel CPUs have a feature called "TSC offsetting" that lets rdtsc execute at full speed but since it doesn't play well with live migrations to other systems, it's disabled by default (I think - I remember I had to jump through a few hoops to enable it.)
AMD and recently Intel CPUs too support something called "TSC scaling" which can also work across migrations (because it doesn't use a fixed offset like TSC offsetting does) but I can't vouch for it, I don't have hardware that is new enough.
Xen and KVM use paravirtualized clocks (pvclocks) where the guest calls out to the host to read the clock. The vDSO handles that transparently if your kernel has paravirt support enabled. It's slower than an untrapped rdtsc instruction but a lot faster than full-blown emulation.
while in browsers
performance.timeOriginis spec'd to return the time origin timestamp, which is a high-resolution UNIX time, rather than a time from an arbitrary position in the past (what it currently returns).Unfortunately, after looking over the libuv documentation I could not find a function that returns something akin to
clock_gettime(CLOCK_REALTIME, tp)on POSIX systems. The ideal solution is, of course, adding such a method to libuv. But if it is not possible to do so in a timely manner, I did outline a hack that allows me to get the correct high-precision value oftimeOriginin jsdom/jsdom#2094 (comment), reproduced below:but it requires at most 1ms of initialization time when
perf_hooksis required.Thoughts?
/cc @bnoordhuis @cjihrig @jasnell