高精度計時
Performance API 允許進行基於時間的、可能具有亞毫秒級解析度的高精度測量,並且具有穩定的單調時鐘,不受系統時鐘偏差或調整的影響。為了進行精確的基準測試,需要高解析度計時器,而不是精度較低且非單調的 Date 時間戳。
本文件概述了 Performance API 中的高精度時間工作原理,以及它與 Date 時間戳的對比。
DOMHighResTimeStamp
高精度計時是透過使用 DOMHighResTimeStamp 型別來表示時間值實現的。單位是毫秒,應精確到 5 微秒 (µs)。然而,如果瀏覽器無法提供精確到 5 微秒的時間值,則可以將該值表示為精確到毫秒的時間。這可能是由於硬體/軟體限制、安全和隱私原因造成的。有關更多資訊,請參閱下面的 降低精度 部分。
Performance API 中的所有時間戳都使用 DOMHighResTimeStamp 型別。以前,Performance API(以及其他 Web API)使用的是 EpochTimeStamp 型別(以前稱為 DOMTimeStamp)。現在不推薦使用這些型別。
Performance.now() vs. Date.now()
JavaScript 將 Date.now() 定義為自 紀元 以來的毫秒數,紀元定義為 1970 年 1 月 1 日午夜(UTC)。另一方面,performance.now() 方法是相對於 Performance.timeOrigin 屬性的。有關更多資訊,請參閱下面的 時間起點 部分。
JavaScript Date 時間會受到系統時鐘偏差或調整的影響。這意味著時間值可能不總是單調遞增的。Date 物件的主要目的是向用戶顯示時間和日期資訊,因此許多作業系統會執行一個定期同步時間的守護程序。時鐘可能每小時被調整幾次,每次幾毫秒。
performance.now() 方法(以及所有其他 DOMHighResTimeStamp 值)提供單調遞增的時間值,不受時鐘調整的影響。這意味著 DOMHighResTimeStamp 值保證至少等於您上次訪問它時的時間,甚至大於它。
Date.now(); // 1678889977578
performance.now(); // 233936
對於效能測量、精確計算幀率 (FPS)、動畫迴圈等,請使用 Performance.now() 提供的單調遞增的高解析度時間,而不是 JavaScript 的 Date.now()。
總結
| - | Performance.now() |
Date.now() |
|---|---|---|
| 解析度 | 亞毫秒 | milliseconds |
| Origin | Performance.timeOrigin |
Unix 紀元(1970 年 1 月 1 日 UTC) |
| 使用時鐘調整 | 否 | 是 |
| 單調遞增 | 是 | 否 |
時間起點
Performance API 使用 Performance.timeOrigin 屬性來確定與效能相關的計時器的基線。所有 DOMHighResTimeStamp 時間都相對於 timeOrigin 屬性。
在 Window 上下文中,此時間起點是導航開始的時間。在 Worker 和 ServiceWorker 上下文中,時間起點是 worker 執行的時間。
在以前的規範版本(Level 1)中,performance.now() 方法過去是相對於導航計時規範中的 performance.timing.navigationStart 屬性的。然而,在後來的規範版本(Level 2)中,這一點發生了變化,performance.now() 現在相對於 Performance.timeOrigin,這避免了跨網頁比較時間戳時的時鐘更改風險。
// Level 1 (clock change risks)
currentTime = performance.timing.navigationStart + performance.now();
// Level 2 (no clock change risks)
currentTime = performance.timeOrigin + performance.now();
同步不同上下文的時間起點
為了考慮視窗和 worker 上下文中不同的時間起點,您應該透過 timeOrigin 屬性來轉換來自 worker 指令碼的時間戳,以便為整個應用程式同步計時。有關同步時間的示例程式碼,請參閱 Performance.timeOrigin 頁面的示例部分。
降低精度
為了提供針對時序攻擊和 指紋識別 的保護,DOMHighResTimeStamp 型別會根據站點隔離狀態進行粗化。
- 隔離上下文中的解析度:5 微秒
- 非隔離上下文中的解析度:100 微秒
要為您的站點應用跨源隔離,請使用 Cross-Origin-Opener-Policy (COOP) 和 Cross-Origin-Embedder-Policy (COEP) 標頭。
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
這些標頭確保頂級文件不與跨源文件共享瀏覽上下文組。 Cross-Origin-Opener-Policy 對您的文件進行程序隔離,潛在攻擊者無法訪問您的全域性物件(如果他們在彈出視窗中開啟它),從而防止了一系列稱為 XS-Leaks 的跨源攻擊。