Skip to content

performance.timeOrigin set incorrectlyΒ #17893

@TimothyGu

Description

@TimothyGu
  • Version: v9.x / master
  • Platform: all
  • Subsystem: perf_hooks
$ ./node -p 'new Date(perf_hooks.performance.timeOrigin).toString()'
Sat Jan 03 1970 08:35:02 GMT+0800 (CST)

while in browsers

> new Date(performance.timeOrigin).toString()
"Thu Dec 28 2017 15:02:33 GMT+0800 (CST)"

performance.timeOrigin is 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 of timeOrigin in jsdom/jsdom#2094 (comment), reproduced below:

const { timeOrigin } = process.binding(...);

// Currently:
// performance.timeOrigin = timeOrigin;

// Offset between the time returned by process.hrtime() and Date.now(). A.k.a. the |t1|
// in W3C [HR-TIME] spec.
const hrtimeOffset = getHrtimeOffset();

const timeOriginTimestamp = hrtimeOffset + timeOrigin;
performance.timeOrigin = timeOriginTimestamp;

function getHrtimeOffset() {
  // Wait at most 1 millisecond, a negligible amount of time for initialization.
  let cur = Date.now();
  const next = cur + 1;
  while (cur !== next) {
    cur = Date.now();
  }

  // At this point cur "just" became equal to the next millisecond -- the unseen digits after cur
  // are approximately all 0, and cur is the closest to the actual value of the UNIX time.
  // Now, get the current global monotonic clock value:

  const [hrSec, hrNS] = process.hrtime();
  const globalMonotonicClockMS = hrSec * 1e3 + hrNS / 1e6;

  // Let |t1| be the DOMHighResTimeStamp representing the high resolution Unix time at
  // which the global monotonic clock is zero.
  // I.e., t1 + globalMonotonicClockMS = cur
  //       t1                          = cur - globalMonotonicClockMS
  return cur - globalMonotonicClockMS;
}

but it requires at most 1ms of initialization time when perf_hooks is required.

Thoughts?

/cc @bnoordhuis @cjihrig @jasnell

Metadata

Metadata

Assignees

Labels

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

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions