在Node.js中单调增加时间

时间:2017-10-26 22:26:03

标签: javascript node.js system-clock

此问题已经针对Javascript here得到了解答,但window.performance.now()显然在Node.js中不可用。

某些应用需要一个稳定的时钟,即一个随时间单调增加的时钟,不受系统时钟漂移的影响。例如,Java有System.nanoTime(),C ++有std::chrono::steady_clock。 Node.js中有这样的时钟吗?

2 个答案:

答案 0 :(得分:7)

结果Node.js中的等价物为process.hrtime()。根据文件:

  

[process.hrtime()返回的时间相对于过去的任意时间而言,与时间无关,因此不受时钟漂移的影响。

实施例

假设我们希望每秒定期调用一次REST端点,处理其结果并将某些内容打印到日志文件中。考虑端点可能需要一段时间来响应,例如,从几百毫秒到多于一秒。我们不希望有两个并发请求,因此setInterval()并不完全符合我们的需求。

一个好的方法是第一次调用我们的函数,执行请求,处理它然后调用setTimeout()并重新安排进行另一次运行。但考虑到我们花在请求上的时间,我们希望每秒做一次。这是使用我们的稳定时钟(这将保证我们不会被系统时钟漂移所欺骗)的一种方法:

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();

我创建了这个帮助函数time(),它将process.hrtime()返回的数组转换为毫秒分辨率的时间戳;这个应用程序只有足够的分辨率。

答案 1 :(得分:1)

NodeJS 10.7.0已添加process.hrtime.bigint()

然后您可以执行以下操作:


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

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

演示节点REPL中的用法:

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

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

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

注意:

  • Number()BigInt转换为常规Number类型,允许使用常规除法运算符将纳秒转换为秒。
  • monotimeDiff()返回以纳秒分辨率传递的墙壁时间差作为浮点数(在进行除法之前转换为Number 之前)。
  • 这假设测得的持续时间没有增长beyond 2^53 ns,实际上只有104天(2**53 ns / 10**9 ns/s / 86400.0 s/day = 104.3 day)。