高精度計時

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 值保證至少等於您上次訪問它時的時間,甚至大於它。

js
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 上下文中,此時間起點是導航開始的時間。在 WorkerServiceWorker 上下文中,時間起點是 worker 執行的時間。

在以前的規範版本(Level 1)中,performance.now() 方法過去是相對於導航計時規範中的 performance.timing.navigationStart 屬性的。然而,在後來的規範版本(Level 2)中,這一點發生了變化,performance.now() 現在相對於 Performance.timeOrigin,這避免了跨網頁比較時間戳時的時鐘更改風險。

js
// 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) 標頭。

http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

這些標頭確保頂級文件不與跨源文件共享瀏覽上下文組。 Cross-Origin-Opener-Policy 對您的文件進行程序隔離,潛在攻擊者無法訪問您的全域性物件(如果他們在彈出視窗中開啟它),從而防止了一系列稱為 XS-Leaks 的跨源攻擊。

另見