Monotonically increasing time in Node.js

纵然是瞬间 提交于 2019-12-08 16:43:41

问题


This question has already been answered for Javascript here, but window.performance.now() is obviously not available in Node.js.

Some applications need a steady clock, i.e., a clock that monotonically increases through time, not subject to system clock drifts. For instance, Java has System.nanoTime() and C++ has std::chrono::steady_clock. Is such clock available in Node.js?


回答1:


Turns out the equivalent in Node.js is process.hrtime(). As per the documentation:

[The time returned from process.hrtime() is] relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift.


Example

Let's say we want to periodically call some REST endpoint once a second, process its outcome and print something to a log file. Consider the endpoint may take a while to respond, e.g., from hundreds of milliseconds to more than one second. We don't want to have two concurrent requests going on, so setInterval() does not exactly meet our needs.

One good approach is to call our function one first time, do the request, process it and then call setTimeout() and reschedule for another run. But we want to do that once a second, taking into account the time we spent making the request. Here's one way to do it using our steady clock (which will guarantee we won't be fooled by system clock drifts):

function time() {
    const [seconds, nanos] = process.hrtime();
    return seconds * 1000 + nanos / 1000000;
}

async function run() {
    const startTime = time();

    const response = await doRequest();
    await processResponse(response);

    const endTime = time();
    // wait just the right amount of time so we run once second; 
    // if we took more than one second, run again immediately
    const nextRunInMillis = Math.max(0, 1000 - (endTime - startTime));
    setTimeout(run, nextRunInMillis);
}

run();

I made this helper function time() which converts the array returned by process.hrtime() to a timestamp with milliseconds resolution; just enough resolution for this application.




回答2:


NodeJS 10.7.0 added process.hrtime.bigint().

You can then do this:


function monotimeRef() {
  return process.hrtime.bigint();
}

function monotimeDiff(ref) {
  return Number(process.hrtime.bigint() - ref) / 10**9;
}

Demonstrating the usage in a Node REPL:

// Measure reference time.
> let t0 = monotimeRef();
undefined

[ ... let some time pass ... ]

// Measure time passed since reference time,
// in seconds.
> monotimeDiff(t0)
12.546663115

Note:

  • Number() converts a BigInt to a regular Number type, allowing for translating from nanoseconds to seconds with the normal division operator.
  • monotimeDiff() returns the wall time difference passed with nanosecond resolution as a floating point number (as of converting to Number before doing the division).
  • This assumes that the measured time duration does not grow beyond 2^53 ns, which is actually just about 104 days (2**53 ns / 10**9 ns/s / 86400.0 s/day = 104.3 day).


来源:https://stackoverflow.com/questions/46964779/monotonically-increasing-time-in-node-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!