1. 引言
用户延迟是 Web 应用的重要质量指标。
虽然基于 JavaScript 的机制可以为应用内的用户延迟测量提供详尽的
仪表采集,但在许多情况下,它们无法提供完整的端到端延迟
全貌。本文档引入了 PerformanceResourceTiming
接口,允许 JavaScript 机制收集与文档资源相关的完整计时
信息。Navigation Timing 2
[NAVIGATION-TIMING-2] 扩展了本规范,为导航提供了
更多相关的计时信息。
例如,下列 JavaScript 展示了测量抓取(fetch)一个资源所花时间的基本方法:
<!doctype html> < html > < head > </ head > < body onload = "loadResources()" > < script > function loadResources() { var start= new Date(). getTime(); var image1= new Image(); var resourceTiming= function () { var now= new Date(). getTime(); var latency= now- start; alert( "End to end resource fetch: " + latency); }; image1. onload= resourceTiming; image1. src= 'https://www.w3.org/Icons/w3c_main.png' ; } </ script > < img src = "https://www.w3.org/Icons/w3c_home.png" > </ body > </ html >
虽然此脚本可以测出获取一个资源所用的时间, 但它无法细分各个阶段的耗时。此外, 脚本也无法轻松测量那些在标记(markup)中描述的资源加载耗时。
为满足对用户体验完整信息的需求,本文档引入了 PerformanceResourceTiming
接口。
该接口允许 JavaScript 机制在应用中提供完整的
客户端延迟测量。有了该接口,上例可以修改为度量用户实际感知到的
资源加载时间。
下列脚本会计算页面上每个资源的抓取耗时,即便这些资源定义在标记中。
此例假定页面托管在 https://www.w3.org 上。还可以利用
PerformanceResourceTiming
接口进一步详细测量抓取每个资源各阶段所用时间。
<!doctype html> < html > < head > </ head > < body onload = "loadResources()" > < script > function loadResources() { var image1= new Image(); image1. onload= resourceTiming; image1. src= 'https://www.w3.org/Icons/w3c_main.png' ; } function resourceTiming() { var resourceList= window. performance. getEntriesByType( "resource" ); for ( i= 0 ; i< resourceList. length; i++ ) { if ( resourceList[ i]. initiatorType== "img" ) { alert( "End to end resource fetch: " + ( resourceList[ i]. responseEnd- resourceList[ i]. startTime)); } } } </ script > < img id = "image0" src = "https://www.w3.org/Icons/w3c_home.png" > </ body > </ html >
2. 术语
当 Foo 实际上是一个接口时,"a Foo object"(一个 Foo 对象)
有时用于代指更准确的 "an object implementing the interface Foo"(实现了接口 Foo 的对象)。
在本规范中,所有时间值都以毫秒为单位衡量, 以文档导航开始时刻为起点 [HR-TIME]。 例如, 文档导航的开始 发生在时间 0。
此时间定义基于 High Resolution Time 规范 [HR-TIME],与 Navigation Timing 规范中使用的时间定义不同。 后者以自 1970 年 1 月 1 日 0 时(UTC)起的毫秒钟数为基准 [NAVIGATION-TIMING-2]。
3. 资源计时
3.1. 简介
The PerformanceResourceTiming
接口用于便于对被 获取的 http(s)
资源进行计时测量。例如,该接口可用于
XMLHttpRequest
对象 [XHR],
HTML 元素 [HTML],例如
iframe、
img、
script、
object、
embed
和
link
(link 类型为 stylesheet),
SVG 元素 [SVG11]
(例如 svg),以及
EventSource。
3.2.
包含在 PerformanceResourceTiming
接口中的资源
本节为非规范性内容。
由非空 client 发起的资源 Request 的
fetch,
会作为 PerformanceResourceTiming
对象包含在该 client 的 全局对象 的
性能时间线(Performance Timeline),除非在 fetch
过程中被从时间线中排除。来自 HTTP 缓存的资源会作为 PerformanceResourceTiming
对象包含在 性能时间线 中。那些已发起 fetch
但随后被中止(例如因网络错误)的资源,也会作为 PerformanceResourceTiming
对象包含在
性能时间线 中,并带有它们的开始和结束时间。
示例:
- 如果两个 HTML
IMG元素使用相同的规范化 URL 作为src属性,则由第一个 HTMLIMG元素发起的该资源的 fetch 会作为一个PerformanceResourceTiming对象包含在 性能时间线 中。用户代理可能不会为第二个 HTMLIMG元素重新请求该 URL,而是使用为第一个 HTMLIMG元素已启动的现有下载。在这种情况下,由第一个IMG元素发起的该资源的 fetch 将是 性能时间线 中的唯一条目。 - 如果通过脚本更改了 HTML
IMG元素的src属性, 则原始资源的 fetch 以及新 URL 的 fetch 都会作为PerformanceResourceTiming对象包含在 性能时间线 中。 - 如果通过标记添加了一个 HTML
IFRAME元素且未指定src属性,用户代理可能会为该IFRAME加载about:blank文档。如果稍后通过脚本动态更改了src属性,用户代理可能会为该IFRAME的新 URL 发起 fetch。在这种情况下,只有该新 URL 的 fetch 会作为一个PerformanceResourceTiming对象包含在 性能时间线 中。 - 如果同一规范化 URL 的
XMLHttpRequest被生成两次,则该资源的两次 fetch 都会作为一个PerformanceResourceTiming对象包含在 性能时间线 中。这是因为第二个XMLHttpRequest的该资源的 fetch 不能重用为第一个XMLHttpRequest发起的下载。 - 如果页面上包含一个 HTML
IFRAME元素,则只有由该IFRAME的src属性请求的资源会作为PerformanceResourceTiming对象包含在父文档的 性能时间线 中。该IFRAME文档请求的子资源会包含在该IFRAME文档的 性能时间线 中,而不是父文档的 性能时间线 中。 - 如果 HTML
IMG元素的源是一个data: URI(参见 [RFC2397]),则该资源不会作为PerformanceResourceTiming对象包含在 性能时间线 中。PerformanceResourceTiming条目仅针对 http(s) 资源报告。 - 如果某个资源的 fetch 因网络错误(例如 DNS、TCP 或 TLS 错误)而被中止,则该 fetch 会作为一个
PerformanceResourceTiming对象包含在 性能时间线 中,并且仅设置startTime、fetchStart、duration和responseEnd。 - 如果某个资源的 fetch 因不满足 fetch 前提(例如 混合内容、CORS 限制、CSP 策略等)而被中止,则该资源不会作为一个
PerformanceResourceTiming对象包含在 性能时间线 中。
3.3. PerformanceResourceTiming 接口
[Exposed =(Window ,Worker )]interface :PerformanceResourceTiming PerformanceEntry {readonly attribute DOMString ;initiatorType readonly attribute DOMString ;deliveryType readonly attribute ByteString ;nextHopProtocol readonly attribute DOMHighResTimeStamp ;workerStart readonly attribute DOMHighResTimeStamp ;redirectStart readonly attribute DOMHighResTimeStamp ;redirectEnd readonly attribute DOMHighResTimeStamp ;fetchStart readonly attribute DOMHighResTimeStamp ;domainLookupStart readonly attribute DOMHighResTimeStamp ;domainLookupEnd readonly attribute DOMHighResTimeStamp ;connectStart readonly attribute DOMHighResTimeStamp ;connectEnd readonly attribute DOMHighResTimeStamp ;secureConnectionStart readonly attribute DOMHighResTimeStamp ;requestStart readonly attribute DOMHighResTimeStamp ;finalResponseHeadersStart readonly attribute DOMHighResTimeStamp ;firstInterimResponseStart readonly attribute DOMHighResTimeStamp ;responseStart readonly attribute DOMHighResTimeStamp ;responseEnd readonly attribute DOMHighResTimeStamp ;workerRouterEvaluationStart readonly attribute DOMHighResTimeStamp ;workerCacheLookupStart readonly attribute DOMString ;workerMatchedRouterSource readonly attribute DOMString ;workerFinalRouterSource readonly attribute unsigned long long ;transferSize readonly attribute unsigned long long ;encodedBodySize readonly attribute unsigned long long ;decodedBodySize readonly attribute unsigned short ;responseStatus readonly attribute RenderBlockingStatusType ;renderBlockingStatus readonly attribute DOMString ;contentType readonly attribute DOMString ; [contentEncoding Default ]object (); };toJSON
一个 PerformanceResourceTiming
具有一个关联的 DOMString
initiator
type。
一个 PerformanceResourceTiming
具有一个关联的 DOMString
delivery
type。
一个 PerformanceResourceTiming
具有一个关联的 DOMString
请求的
URL。
一个 PerformanceResourceTiming
具有一个关联的 DOMString
缓存模式
(空字符串、"local",或
"validated")。
一个 PerformanceResourceTiming
具有关联的 fetch timing info,该项 计时信息。
一个 PerformanceResourceTiming
具有关联的 响应正文信息,该项 资源信息。
一个 PerformanceResourceTiming
具有关联的
状态
响应状态。
一个 PerformanceResourceTiming
具有关联的
RenderBlockingStatusType
阻塞渲染状态(render-blocking status)。
当调用 toJSON 时,应为 PerformanceResourceTiming
运行 默认的 toJSON 步骤。
initiatorType 的 getter 步骤应返回 该条目的 initiator type,即对于 this。
initiatorType 返回以下某一值:
-
"navigation":如果该请求是一个 导航请求; -
"body":如果该请求是处理body元素上已废弃的background属性的结果。 -
"css":如果该请求是处理 CSS url() 指令的结果,例如@import url()或background: url(); [CSS-VALUES]注意:通过 CSS 中的
@font-face指定的字体资源请求属于处理 CSS 指令的结果。因此,该字体资源的initiatorType为"css"。 -
"script":如果该请求是加载任何 脚本 的结果(包括传统脚本script、模块脚本 module script,或Worker)。 -
"xmlhttprequest":如果该请求是处理XMLHttpRequest的结果; -
"font":如果该请求是处理字体的结果。这可能发生在字体请求后续资源时,例如使用增量字体传输(Incremental Font Transfer)[INCREMENTAL_FONT_TRANSFER] 的情况。 -
"fetch":如果该请求是处理fetch()方法的结果; -
"beacon":如果该请求是处理sendBeacon()方法的结果; [BEACON] -
"video":如果该请求是处理video元素的poster或src的结果。 -
"audio":如果该请求是处理audio元素的src的结果。 -
"track":如果该请求是处理track元素的src的结果。 -
"img":如果该请求是处理img元素的src或srcset的结果。 -
"image":如果该请求是处理 image 元素的结果。 [SVG2] -
"input":如果该请求是处理某个input元素(其type为 image)的结果。 -
"ping":如果该请求是处理a元素的ping的结果。 -
"iframe":如果该请求是处理iframe的src的结果。 -
"frame":如果该请求是加载一个frame的结果。 -
"embed":如果该请求是处理embed元素的src的结果。 -
"link":如果该请求是处理link元素的结果。 -
"object":如果该请求是处理object元素的结果。 -
"early-hints":如果该请求是处理 Early Hints [EARLY_HINTS] 响应的结果。 -
"other":如果上述条件都不匹配。
initiatorType 的设置是在报告资源计时条目的不同位置完成的,例如在 fetch
规范中。
deliveryType 的 getter 步骤应返回 该条目的 delivery type,即对于 this。
deliveryType 返回以下某一值:
-
"cache":如果 cache mode 不是空字符串。 - 空字符串
"":如果上述条件都不匹配。
预计该项将在未来规范更新中扩展,例如用于描述消费预加载资源和预取导航请求的情况。
workerStart 的 getter 步骤为:对 转换 fetch 时间戳,作用于 this 的 timing info 的 final service worker start time,以及 相关全局对象 for this。详见 HTTP fetch 以获取更多信息。
redirectStart 的 getter 步骤为: 转换 fetch 时间戳,作用于 this 的 timing info 的 redirect start time 及 相关全局对象 for this。详见 HTTP-redirect fetch 以获取更多信息。
redirectEnd 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 redirect end time 及 相关全局对象 for this。详见 HTTP-redirect fetch 以获取更多信息。
fetchStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 post-redirect start time 及 相关全局对象 for this。 详见 HTTP fetch 以获取更多信息。
domainLookupStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final connection timing info 的 domain lookup start time 及 相关全局对象 for this。 详见 Recording connection timing info 以获取更多信息。
domainLookupEnd 的 getter 步骤 为 转换 fetch 时间戳,作用于 this 的 timing info 的 final connection timing info 的 domain lookup end time 及 相关全局对象 for this。 详见 Recording connection timing info 以获取更多信息。
connectStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final connection timing info 的 connection start time 及 相关全局对象 for this。详见 Recording connection timing info 以获取更多信息。
connectEnd 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final connection timing info 的 connection end time 及 相关全局对象 for this。 详见 Recording connection timing info 以获取更多信息。
secureConnectionStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final connection timing info 的 secure connection start time 及 相关全局对象 for this。 详见 Recording connection timing info 以获取更多信息。
nextHopProtocol 的 getter 步骤 为对 isomorphic decode this 的 timing info 的 final connection timing info 的 ALPN 协议协商 进行解码。详见 Recording connection timing info 以获取更多信息。
Issue 221 建议 移除 nextHopProtocol 的支持,因为它可能暴露用户的网络配置信息。
requestStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final network-request start time 及 相关全局对象 for this。详见 HTTP fetch 以获取更多信息。
firstInterimResponseStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 first interim network-response start time,以及 相关 全局对象 for this。详见 HTTP fetch 以获取更多信息。
finalResponseHeadersStart 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 final network-response start time 及 相关全局对象 for this。详见 HTTP fetch 以获取更多信息。
responseStart 的 getter 步骤为
返回 this
的
firstInterimResponseStart
如果该值不为
0;否则返回 this 的
finalResponseHeadersStart。
responseEnd 的 getter 步骤为 转换 fetch 时间戳,作用于 this 的 timing info 的 end time,以及 相关全局对象 for this。详见 fetch 以获取更多信息。
encodedBodySize 的 getter 步骤 为返回 this 的 resource info 的 encoded size。
decodedBodySize 的 getter 步骤 为返回 this 的 resource info 的 decoded size。
transferSize 的 getter 步骤为:
-
如果 this 的 cache mode 为 "
local",则返回 0。 -
如果 this 的 cache mode 为 "
validated",则返回 300。 -
加到
transferSize的常数用于替代暴露 HTTP 头的总字节大小,因为那可能泄露某些 cookie 的存在。参见 该问题。
responseStatus 的 getter 步骤是 返回 this 的 响应状态。
responseStatus 由 Fetch
决定。对于跨域的 no-cors 请求,响应状态将为
0,因为响应将是一个 不透明的过滤响应。
contentType 的 getter 步骤是返回 this 的 资源信息 中的 内容类型。
contentEncoding 的 getter 步骤 是返回 this 的 资源信息 中的 内容编码。
renderBlockingStatus 的 getter 步骤是:如果 blocking 条件成立(即 this 的 timing info 中的 render-blocking 为 true),则返回 blocking;否则返回 non-blocking。
workerRouterEvaluationStart 的 getter 步骤是返回 this 的 timing info 中的 service worker 计时信息 的 worker 路由评估开始时间。
workerCacheLookupStart 的 getter 步骤是返回 this 的 timing info 中的 service worker 计时信息 的 worker 缓存查找开始时间。
workerMatchedRouterSource 的 getter 步骤是返回 this 的 timing info 中的 service worker 计时信息 的 worker 匹配的路由源。
workerFinalRouterSource 的 getter 步骤是返回 this 的 timing info 中的 service worker 计时信息 的 worker 最终的路由源。
实现 PerformanceResourceTiming
的用户代理需要在 supportedEntryTypes
中包含 "resource"。这允许开发者检测对资源计时的支持。
3.3.1. RenderBlockingStatusType 枚举
enum {RenderBlockingStatusType ,"blocking" };"non-blocking"
这些值定义如下:
- blocking
- 该资源可能阻塞渲染。
- non-blocking
- 该资源不会阻塞渲染。
3.4.
对 Performance 接口的扩展
用户代理可以选择限制包含为 PerformanceResourceTiming
对象在 性能时间线(Performance Timeline) 中的数量 [PERFORMANCE-TIMELINE-2]。本节扩展了
Performance
接口,以允许控制所存储的 PerformanceResourceTiming
对象的数量。
推荐的 PerformanceResourceTiming
对象的最小数量为 250,但用户代理可对其进行更改。
可调用 setResourceTimingBufferSize 请求更改此限制。
每个 ECMAScript 全局环境 具有:
- 一个 资源计时缓冲区大小限制, 初始应为 250 或更大。
- 一个 资源计时缓冲区当前大小, 初始为 0。
- 一个 资源计时缓冲区已满事件待定标志, 初始为 false。
- 一个 资源计时二级缓冲区当前大小, 初始为 0。
- 一个 资源计时二级缓冲区 用于存放
PerformanceResourceTiming对象,初始为空。
partial interface Performance {undefined ();clearResourceTimings undefined (setResourceTimingBufferSize unsigned long );maxSize attribute EventHandler ; };onresourcetimingbufferfull
Performance 接口在 [HR-TIME] 中定义。
方法 clearResourceTimings 运行以下步骤:
- 从
PerformanceResourceTiming对象中删除性能条目缓冲区(performance entry buffer)中的所有条目。 - 将 资源计时缓冲区当前大小 设为 0。
方法 setResourceTimingBufferSize 运行以下步骤:
- 将 资源计时缓冲区大小限制 设为
maxSize 参数。如果 maxSize 参数小于 资源计时缓冲区当前大小,则不应从
PerformanceResourceTiming对象中移除任何条目以缩减缓冲区。
属性 onresourcetimingbufferfull 是下文描述的
resourcetimingbufferfull 事件的事件处理器。
要检查 是否可以添加资源计时条目,按如下步骤执行:
- 如果 资源计时缓冲区当前大小 小于 资源计时缓冲区大小限制,则返回 true。
- 返回 false。
要将 PerformanceResourceTiming 条目 new entry 添加到 性能条目缓冲区,按如下步骤执行:
-
如果 是否可以添加资源计时条目 返回
true 且
资源计时缓冲区已满事件挂起标志
为 false,执行下列子步骤:
- 将 new entry 添加到 性能条目缓冲区。
- 将 资源计时缓冲区当前大小 增加 1。
- 返回。
-
如果 资源计时缓冲区已满事件挂起标志
为 false,执行下列子步骤:
- 将 资源计时缓冲区已满事件挂起标志 设为 true。
- 在 performance timeline 任务源 上 排队一个任务 ,以运行 触发缓冲区已满事件。
- 将 new entry 添加到 资源计时二级缓冲区。
- 将 资源计时二级缓冲区当前大小 增加 1。
要 复制二级缓冲区,按如下步骤执行:
-
当 资源计时二级缓冲区 不为空且
是否可以添加资源计时条目 返回
true 时,执行下列子步骤:
- 令 entry 为 资源计时二级缓冲区 中最早的
PerformanceResourceTiming。 - 将 entry 添加到 性能条目缓冲区 的末尾。
- 将 资源计时缓冲区当前大小 增加 1。
- 从 资源计时二级缓冲区 移除 entry。
- 将 资源计时二级缓冲区当前大小 减 1。
- 令 entry 为 资源计时二级缓冲区 中最早的
要 触发缓冲区已满事件,按如下步骤执行:
-
当 资源计时二级缓冲区 不为空时,执行下列子步骤:
- 令 number of excess entries before 等于 资源计时二级缓冲区当前大小。
- 如果 是否可以添加资源计时条目 返回 false,
则
触发名为
resourcetimingbufferfull的事件, 目标为Performance对象。 - 执行 复制二级缓冲区。
- 令 number of excess entries after 为 资源计时二级缓冲区当前大小。
- 如果 number of excess entries before 小于等于 number of excess entries after,则移除 资源计时二级缓冲区 中的所有条目, 将 资源计时二级缓冲区当前大小 设为 0,并 中止这些步骤。
-
将 资源计时缓冲区已满事件挂起标志
设为 false。
这意味着如果
resourcetimingbufferfull事件处理器新增缓冲区空间 小于或等于它新增的资源条目,则部分溢出条目会从缓冲区被丢弃。 开发者需确保resourcetimingbufferfull事件处理器调用clearResourceTimings或 通过调用setResourceTimingBufferSize适当扩展缓冲区。
3.5. 跨域资源
3.5.1. 介绍
如 Fetch 中所述,对跨域资源的请求被作为 PerformanceResourceTiming
对象包含在
性能时间线 中。
如果对跨域资源执行 timing allow check
算法失败,则该条目将成为一个 不透明条目(opaque
entry)。此类条目的大部分属性会被屏蔽,以防泄露未被其他方式公开的跨域数据。因此,对于一个 不透明条目,以下属性将始终返回零或空字符串:
redirectStart,
redirectEnd,
workerStart,
domainLookupStart,
domainLookupEnd,
connectStart,
connectEnd,
requestStart,
firstInterimResponseStart,
finalResponseHeadersStart,
responseStart,
secureConnectionStart,
和
nextHopProtocol。
有些属性,例如 contentType、
encodedBodySize、
和
decodedBodySize
在响应为 CORS
跨域 时会被设置为零(或者在 contentType 的情况下为空字符串)。
transferSize
既受 timing allow check 的影响,也受 CORS
跨域 状态的影响。
对于由 service worker 使用 respondWith()
处理的请求,
报告的计时数据反映的是客户端与 service worker 之间的交互,而不是 service worker 自身的内部网络活动。例如,service worker
可能会以跨域响应来响应同源请求,或反之,或者为任一请求返回缓存或合成响应。因此,从 service worker 转发的资源并不能完整描述获取该资源的全过程,且不会通过 timing allow check。要获得这些 fetch
的完整信息,可以检查 service worker 自身的性能时间线。[SERVICE-WORKERS]
更多细节见 HTTP Fetch
#4 - 当没有来自 service worker 的响应时,才执行 timing allow check。此外,在 respondWith()
算法中克隆的 response 不携带内部 fetch 的 fetch timing info,因为该信息是附加到 fetch 而不是附加到 response 上的。
3.5.2.
Timing-Allow-Origin 响应头
服务器端应用可以返回 Timing-Allow-Origin HTTP 响应头,以允许用户代理向指定的文档源完整地公开那些因跨域限制而被置为零的属性值。
Timing-Allow-Origin HTTP 响应头字段可用于传达一项策略,指示允许哪些源查看那些因跨域限制而被置为零的属性值。该头的值以如下 ABNF 表示(使用 List Extension,与 [RFC5234] 配合使用,以及 列表扩展 与 [RFC9110]):
Timing-Allow-Origin = 1#( origin-or-null / wildcard )
发送方可以生成多个 Timing-Allow-Origin 头字段。接收方可以通过将后续每个字段值按顺序追加并以逗号分隔的方式组合多个 Timing-Allow-Origin 头字段值。
即便存在 Timing-Allow-Origin HTTP 响应头字段,用户代理仍可能强制执行跨域限制并将 transferSize、encodedBodySize 和 decodedBodySize 属性设为零。如果这样做,它也可能将 deliveryType 设为 ""。
Timing-Allow-Origin 头在 FETCH 中处理,以据此计算相关属性。
Timing-Allow-Origin 头可能作为缓存响应的一部分到达。在缓存重新验证的情况下,根据 RFC 7234,该头的值可能来自重新验证响应;如果那里没有,则可能来自原始缓存资源。
3.5.3. IANA 考虑事项
本节将 Timing-Allow-Origin 注册为 临时消息头(Provisional Message Header)。
- 头字段名称:
-
Timing-Allow-Origin
- 适用协议:
- http
- 状态:
- provisional
- 作者/变更控制者:
- W3C
- 规范文档:
- § 3.5.2 Timing-Allow-Origin Response Header
3.6. 资源计时属性
本节为非规范性内容。
下图说明了 PerformanceResourceTiming 接口定义的计时属性。括号内的属性可能在对跨域资源进行 fetch 时不可用。用户代理可能会在计时之间进行内部处理,从而允许非规范性的计时间隔。
PerformanceResourceTiming
接口定义的计时属性。括号内的属性表示如果资源未通过 timing
allow
check 算法,则这些属性可能不可用。
4. 创建资源计时条目
若要标记资源计时,给定一个fetch 计时信息 timingInfo, 一个 DOMString requestedURL, 一个 DOMString initiatorType, 一个全局对象 global, 一个字符串 cacheMode, 一个响应体信息 bodyInfo, 一个状态 responseStatus,还有一个可选的字符串 deliveryType (默认为空字符串),请执行以下步骤:
- 在
global 的realm中,
创建一个
PerformanceResourceTiming对象 entry。 - 为 entry,以及 initiatorType、requestedURL、timingInfo、 cacheMode、bodyInfo、responseStatus 和 deliveryType 设置资源计时条目。
- 将 PerformanceEntry entry 排队。
- 添加 entry 到 global 的 性能条目缓冲区。
若要为
PerformanceResourceTiming
entry 设置资源计时条目,
给定 DOMString
initiatorType,DOMString requestedURL,
fetch 计时信息
timingInfo,一个 DOMString cacheMode,
响应体信息
bodyInfo,
一个状态
responseStatus,以及一个可选的 DOMString deliveryType(默认为空字符串),请执行以下步骤:
- 断言 cacheMode 是空字符串、"
local" 或 "validated"。 - 令 global 为 entry 的 相关全局对象。
- 初始化 entry,传入
转换
timingInfo 的 开始时间(以 global 为准)、
"
resource"、requestedURL,以及 转换 timingInfo 的 结束时间(以 global 为准)的结果。 - 将 entry 的 发起者类型 设为 initiatorType。
- 将 entry 的 请求 URL 设为 requestedURL。
- 将 entry 的 计时信息 设为 timingInfo。
- 将 entry 的 资源信息 设为 bodyInfo。
- 将 entry 的 缓存模式 设为 cacheMode。
- 将 entry 的 响应状态 设为 responseStatus。
- 如果 deliveryType 是空字符串且 cacheMode 非空,
则将 deliveryType 设为 "
cache"。 - 将 entry 的 分发类型 设为 deliveryType。
要转换
fetch 时间戳,给定 DOMHighResTimeStamp
ts 和 全局对象 global,执行如下步骤:
- 如果 ts 为零,返回零。
- 否则,返回以 ts 和 global 计算得到的 相对高分辨率粗略时间。
5. 安全性注意事项
PerformanceResourceTiming
接口会将某一资源的计时信息暴露给任何请求该资源的网页或 worker。为限制对此
PerformanceResourceTiming
接口的访问,默认会强制执行
同源策略,并如HTTP fetch所述,将某些属性设为零。资源提供者可通过添加
Timing-Allow-Origin HTTP 响应头(指定允许访问计时信息的域名),显式允许对该资源收集全部计时信息。
6. 隐私注意事项
统计指纹识别是一个隐私问题,恶意网站可能通过测量第三方网站资源的缓存命中和未命中的计时,
来判断用户是否访问过某个第三方网站。虽然 PerformanceResourceTiming
接口为文档中的资源提供计时信息,但资源上的 load 事件已可实现有限地检测缓存命中与否,并且
HTTP Fetch 的跨域限制可防止任何额外信息的泄漏。
7. 致谢
感谢 Anne Van Kesteren、Annie Sullivan、Arvind Jain、Boris Zbarsky、Darin Fisher、Jason Weber、Jonas Sicking、James Simonsen、 Karen Anderson、Kyle Scholz、Nic Jansma、Philippe Le Hegaret、 Sigbjørn Vik、Steve Souders、Todd Reifsteck、Tony Gentilcore、William Chan 和 Alex Christensen 对本工作的贡献。