高精度计时

性能 API 允许进行高精度测量,这些测量基于潜在亚毫秒级分辨率的时间和稳定的单调时钟,该时钟不受系统时钟偏差或调整的影响。高分辨率计时器需要用于精确基准测试,而不是不太精确且非单调的 Date 时间戳。

本页提供了关于高精度时间如何在性能 API 中工作以及它如何与 Date 时间戳进行比较的概述。

DOMHighResTimeStamp

高精度计时是通过使用 DOMHighResTimeStamp 类型来实现的,该类型用于时间值。该单位为毫秒,应精确到 5 µs(微秒)。但是,如果浏览器无法提供精确到 5 微秒的时间值,则浏览器可以将该值表示为精确到毫秒的毫秒时间。这可能是由于硬件/软件限制、安全和隐私原因造成的。有关更多信息,请参见以下有关 精度降低 的部分。

性能 API 中的所有时间戳都使用 DOMHighResTimeStamp 类型。以前,性能 API(和其他 Web API)使用 EpochTimeStamp 类型(以前称为 DOMTimeStamp)。现在不鼓励使用这些类型。

Performance.now()Date.now()

JavaScript 将 Date.now() 定义为自 纪元 起经过的毫秒数,纪元定义为 1970 年 1 月 1 日星期四凌晨 0 点(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()
分辨率 亚毫秒 毫秒
起点 Performance.timeOrigin Unix 纪元(1970 年 1 月 1 日,UTC)
使用时钟调整
单调递增

时间起点

性能 API 使用 Performance.timeOrigin 属性来确定性能相关时间戳的基线。所有 DOMHighResTimeStamp 时间都相对于 timeOrigin 属性。

在 Window 上下文中,此时间起点是导航开始的时间。在 WorkerServiceWorker 上下文中,时间起点是运行工作线程的时间。

在规范的先前版本(级别 1)中,performance.now() 方法以前是相对于 performance.timing.navigationStart 属性(来自导航计时规范)的。但是,这种情况在规范的后续版本(级别 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();

同步跨上下文的时间起点

为了解决窗口和工作线程上下文中不同的时间起点,您应该使用 timeOrigin 属性转换来自工作线程脚本的时间戳,以便整个应用程序的时间同步。有关同步时间的示例代码,请参见 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 的跨源攻击。

另请参见