前端Tips#4 - 用 process.hrtime 獲取納秒級的計時精度

本文同步自 JSCON簡時空 - 前端Tips 專欄#4,點擊閱讀

視頻講解

視頻地址html

文字講解

若是去測試代碼運行的時長,你會選擇哪一個時間函數? 通常第一時間想到的函數是 Date.nowDate.getTime前端

一、先講結論

在 Node.js 程序中,優先選 process.hrtime,其次選 performance.now,最後纔會是 Date.nownode

之因此這麼選,是基於 精度時鐘同步 兩方面考慮的。git

二、知識講解

首先看一下 Date.now 的缺點github

  1. 返回的時間精度爲 毫秒(10^-3)級別,精度不夠;
  2. 受到系統時間影響,也有可能被其餘軟件調整所影響

爲了得到更高精度、且和系統時間無關的時間,W3C 制定了 High Resolution Time Level 2 標準,其中的 6. Monotonic Clock 章節就規定了標準實現方須要提供 「單調遞增」 的全局系統時鐘:編程

單調遞增時鐘

在 Node.js 和 瀏覽器中都實現了該標準,具體的實現就是 performance 對象。咱們能夠經過 performance.now 獲取相對起點的時間戳,具有如下幾個特性:segmentfault

  1. 和 JS 中其餘可用的時間類函數(好比 Date.now )不一樣的是,performance.now() 返回的時間使用了一個浮點數來達到 微秒(10^-6) 級別的精確度
  2. 時間以一個 恆定的速率 慢慢 增長 的,它不會受到系統時間的影響(不會被其餘軟件所調整)
  3. 從標準定義看,能夠存在 clock drift (容許時鐘漂移)

時鐘漂移

這裏大體說一下 clock drift 的概念,它是源於 時鐘同步 概念。時鐘同步( Clock synchronization)是計算機科學與工程學中的一個概念,旨在協調多個獨立的時鐘。現實中的多個時鐘,即便時間已調至一致,但在一段時間後依然會由於時鐘漂移(即 clock drift)而顯示不一樣的時間,由於它們計時的速率會略有差別。

是否有更精細的時鐘存在呢?api

有的,在 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);

到這裏本節主要內容講完了,也就天然而然得到本節剛開始的結論。

三、小知識

若是你使用 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);

四、參考文章


關於 「前端Tips專欄」

前端Tips」專欄,隸屬於 JSCON 專欄系列,設計初衷是快速獲取前端小技巧知識,取材普遍,涵蓋前端編程諸多領域。有兩種方式獲取歷史 tips:

① 在公衆號內回「tips」 + 「年份」 + 「A(或者B)」 獲取半年度 tips。例如:回覆 「tips2020A」 便可獲取 2020 年上半年 tips 列表

② 前往網站:https://boycgit.github.io/fe-... ,裏面提供了搜索功能

歡迎你們關注個人知識專欄,更多內容等你來挖掘

「可在微信內搜索 「JSCON簡時空」或 「iJSCON」 關注」

我的微信公衆號

相關文章
相關標籤/搜索