前端Tips#4 - 用 process.hrtime 获取纳秒级的计时精度

视频讲解

音频讲解

文字讲解

如果去测试代码运行的时长,你会选择哪个时间函数?一般第一时间想到的函数是 Date.nowDate.getTime

1、先讲结论

在 Node.js 程序中,优先选 process.hrtime,其次选 performance.now,最后才会是 Date.now

之所以这么选,是基于 精度时钟同步 两方面考虑的。

2、知识讲解

首先看一下 Date.now 的缺点

  1. 返回的时间精度为 毫秒(10^-3)级别,精度不够;

  2. 受到系统时间影响,也有可能被其他软件调整所影响

为了获得更高精度、且和系统时间无关的时间,W3C 制定了 High Resolution Time Level 2 标准,其中的 6. Monotonic Clock 章节就规定了标准实现方需要提供 “单调递增” 的全局系统时钟:

单调递增时钟

在 Node.js 和 浏览器中都实现了该标准,具体的实现就是 performance 对象。我们可以通过 performance.now 获取相对起点的时间戳,具备以下几个特性:

  1. 和 JS 中其他可用的时间类函数(比如 Date.now )不同的是,performance.now() 返回的时间使用了一个浮点数来达到 微秒(10^-6) 级别的精确度

  2. 时间以一个 恒定的速率 慢慢 增加 的,它不会受到系统时间的影响(不会被其他软件所调整)

  3. 从标准定义看,可以存在 clock drift (允许时钟漂移)

时钟漂移

这里大致说一下 clock drift 的概念,它是源于 时钟同步 概念。时钟同步(Clock synchronization)是计算机科学与工程学中的一个概念,旨在协调多个独立的时钟。现实中的多个时钟,即使时间已调至一致,但在一段时间后依然会因为时钟漂移(即clock drift)而显示不同的时间,因为它们计时的速率会略有差异。

是否有更精细的时钟存在呢?

有的,在 Node.js 环境中就提供了 process.hrtime 方法:

  1. 在 node v0.7.6 版本中新增,兼容性很好(毕竟现在都 v12 LTS 版本了)

  2. 精度高达 纳秒(10^-9) 级别

  3. 不存在 时钟漂移 (clock drift)

可以说 process.hrtime 方法是 专为测量时间间隔而打造 的。

注:浏览器环境没有这个 hrtime 方法,因此浏览器环境所能达到的最高精度也就用 performance.now 的微秒级别(当然各个浏览器实现也是有差异)

只不过这个方法使用需要注意一下,首次调用返回的 time 需要作为后面调用的入参:

const NS_PER_SEC = 1e9;
const time = process.hrtime(); // 这里第一次调用,返回 time 变量
// [ 1800216, 25 ]

setTimeout(() => {
  const diff = process.hrtime(time); // 用第一次返回的 time 变量作为入参放在第二次调用中,从而获取 diff 时间差值
  // [ 1, 552 ]

  console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`);
  // Benchmark took 1000000552 nanoseconds
}, 1000);

到这里本节主要内容讲完了,也就自然而然获得本节刚开始的结论。

3、小知识

如果你使用 Node.js V10.7.0 以上的版本,还可以使用 hrtime.bigint 方法,它是 process.hrtimebigint 版本(bigint 类型从 v10.4 开始支持),返回当前的高精度实际时间。

这方法使用起来比 process.hrtime 更加方便,因为它不用额外的 time 入参,直接通过两次调用结果相减就能获得计算时间差:

const start = process.hrtime.bigint();
// 191051479007711n

setTimeout(() => {
  const end = process.hrtime.bigint();
  // 191052633396993n

  console.log(`基准测试耗时 ${end - start} 纳秒`);
  // 基准测试耗时 1154389282 纳秒
}, 1000);

       

REFERENCE

   参考文档

  • High Resolution Time Level 2:w3c 中高精度时间的标准

  • MDN - Performance.now:MDN 上 performance.now 的 API 文档

  • Creating a timestamp:言简意赅的总结,本文的选材最初就是来源于此

  • 如何理解 clock drift 和 clock skew 这两个概念呢?:知乎上对这两个概念的回答

  • Measure process time with Node Js?:SOF 上对该问题的解答,也是用 process.hrtime 进行高精度时间测量

  • 如何在Node.js中获得微时间?:可以看一下这个问题

  • 初探 performance – 监控网页与程序性能:window.performance 提供了一组精确的数据,经过简单的计算就能得出一些网页性能数据

  • 页面性能监测之performance:详细介绍如何利用 performance 对象来评测页面性能

嘿,请问如何获取往期 tips ?

有两种方式哈:

① 在公众号内回 "tips" + "年份"+"A"(或"B") 就可以。例如:回复 “tips2020A” 即可获取第 2020 上半年 的 tips

② 前往网站:https://boycgit.github.io/fe-program-tips里面提供了搜索功能

关于「JSCON专栏﹒前端Tips」

前端Tips”专栏,隶属于 JSCON 专栏系列,设计初衷是快速获取前端小技巧知识,取材广泛,涵盖前端编程诸多领域。设计初衷是快速消费类知识,所以每个 tips 阅读耗时大约 5 分钟。为方便读者在不同场合阅读,每篇 tips 配有视频音频文字,挑自己喜欢方便的就行。

欢迎大家关注我的知识专栏,更多内容等你来挖掘

微信中外链无法点击,完整版请点击下方的"阅读原文"  


发布了40 篇原创文章 · 获赞 211 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览