高精度计时
性能 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
值将至少等于(如果不是大于)上次访问它的值。
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 上下文中,此时间起点是导航开始的时间。在 Worker
和 ServiceWorker
上下文中,时间起点是运行工作线程的时间。
在规范的先前版本(级别 1)中,performance.now()
方法以前是相对于 performance.timing.navigationStart
属性(来自导航计时规范)的。但是,这种情况在规范的后续版本(级别 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();
同步跨上下文的时间起点
为了解决窗口和工作线程上下文中不同的时间起点,您应该使用 timeOrigin
属性转换来自工作线程脚本的时间戳,以便整个应用程序的时间同步。有关同步时间的示例代码,请参见 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 的跨源攻击。