1. 简介
本节为非规范性内容。
准确衡量网页应用的性能特性是提升网页速度的重要部分。虽然 JavaScript 机制(如[JSMEASURE]所述)可为应用内 用户延迟测量提供全面的工具,但 在很多情况下,无法提供完整或详细的端到端延迟图景。 例如,下方 JavaScript 展示了测量页面完全加载时间的一个简单尝试:
< html > < head > < script type = "text/javascript" > var start= new Date(). getTime(); function onLoad() { var now= new Date(). getTime(); var latency= now- start; alert( "page loading time: " + latency); } </ script > </ head > < body onload = "onLoad()" > <!- 主页面内容从这里开始 --> </ body > </ html >
上述脚本是计算页面加载所需时间, 在head 内首段 JavaScript 执行之后,但 不能反映页面从服务器获取或页面初始化生命周期的耗时。
本规范定义了 PerformanceNavigationTiming
接口,该接口参与[PERFORMANCE-TIMELINE-2]以存取
与文档导航相关的高精度性能指标数据。由于 PerformanceNavigationTiming
接口采用 [HR-TIME],
所有时间值均以条目的
时间原点
与其相关设置对象为基准衡量。
例如,如果 response end 在导航开始后 100ms 发生,PerformanceNavigationTiming
数据可能如下:
startTime: 0.000 // 导航请求开始时刻 responseEnd: 100.000 // 最后接收字节的高精度时间
如下脚本展示开发者如何使用
PerformanceNavigationTiming
接口获取与文档导航相关的精确时序数据:
< script > function showNavigationDetails() { // 获取首个条目 const [ entry] = performance. getEntriesByType( "navigation" ); // 在开发者控制台以表格展示 console. table( entry. toJSON()); } </ script > < body onload = "showNavigationDetails()" >
2. 术语
表达 “一个Foo对象”,如 Foo 实际为接口,有时用于代替更准确的说法 “实现 Foo接口的对象”。
术语当前文档 指的是与Window 对象最新 Document 对象关联的文档。
在整个规范中,所有时间值均以自文档导航开始起的毫秒计。比如,文档导航起始时间为 0。 “当前时间”指从文档导航起至此刻经过的毫秒数。 这一时间定义基于[HR-TIME]规范。
3. 导航时序
3.1. 与PerformanceEntry
接口的关系
PerformanceNavigationTiming
接口扩展了
PerformanceEntry
接口的以下属性:
entryTypegetter 步骤要返回DOMString"navigation"。startTimegetter 步骤要返回时间值为 0 的DOMHighResTimeStamp。durationgetter 步骤要返回等于loadEventEnd与 this 的startTime之差的DOMHighResTimeStamp。
实现 PerformanceNavigationTiming
的用户代理需在
"navigation" 加入
supportedEntryTypes
,用于 Window
上下文。这允许开发者检测导航时序支持。
3.2.
与PerformanceResourceTiming接口的关系
PerformanceNavigationTiming
接口扩展了
PerformanceResourceTiming
接口的以下属性:
-
redirectStartgetter 步骤需执行如下操作:- 若 this 的 重定向次数为 0,返回 0。
- 否则返回 this 的
redirectStart。
-
redirectEndgetter 步骤需执行如下操作:- 若 this 的 重定向次数为 0,返回 0。
- 否则返回 this 的
redirectEnd。
虽然 `redirectStart` 和 `redirectEnd` 在
PerformanceResourceTiming中暴露, 但在导航时序语境下含义不同,遇到跨域重定向导航时返回 0。 -
workerStartgetter 步骤执行如下:- 令 workerTiming 为 this 的 service worker 时序。
- 若 workerTiming 为 null,则返回 this 的原型的 `workerStart`。
- 返回 workerTiming 的 start time。
虽然 `workerStart` 在
PerformanceResourceTiming中暴露, 但与导航时序意义不同,导航 可能 会触发 service worker 的激活或运行。 在导航时序中,`workerStart` 返回 worker 激活或启动前的时间戳。详见 [service-workers]。 -
fetchStartgetter 步骤执行如下:- 令 workerTiming 为 this 的 service worker 时序。
- 若 workerTiming 为 null,则返回 this 的原型的 `fetchStart`。
- 返回 workerTiming 的 fetch event dispatch time。
导航中若使用 service worker,此 `fetchStart` 重载 意义与
PerformanceResourceTiming不同。其返回FetchEvent分发给 service worker 之前的时间戳。 文档导航时序条目的 `workerStart` 与 `fetchStart` 差值可以粗略反映 worker 初始化或激活的耗时。详见 [service-workers]。
只有 当前文档
资源包含在性能时间线上;性能时间线中只有一个
PerformanceNavigationTiming
对象。
3.3. PerformanceNavigationTiming 接口
[Exposed =Window ]interface :PerformanceNavigationTiming PerformanceResourceTiming {readonly attribute DOMHighResTimeStamp ;unloadEventStart readonly attribute DOMHighResTimeStamp ;unloadEventEnd readonly attribute DOMHighResTimeStamp ;domInteractive readonly attribute DOMHighResTimeStamp ;domContentLoadedEventStart readonly attribute DOMHighResTimeStamp ;domContentLoadedEventEnd readonly attribute DOMHighResTimeStamp ;domComplete readonly attribute DOMHighResTimeStamp ;loadEventStart readonly attribute DOMHighResTimeStamp ;loadEventEnd readonly attribute NavigationTimingType ;type readonly attribute unsigned short ;redirectCount readonly attribute DOMHighResTimeStamp ;criticalCHRestart readonly attribute NotRestoredReasons ?;notRestoredReasons readonly attribute PerformanceTimingConfidence ; [confidence Default ]object (); };toJSON
PerformanceNavigationTiming
关联一个
文档加载时序信息 文档加载时序。
PerformanceNavigationTiming
关联一个
文档卸载时序信息 前文档卸载时序。
PerformanceNavigationTiming
关联一个
数值 重定向计数。
PerformanceNavigationTiming
关联一个
NavigationTimingType
导航类型。
PerformanceNavigationTiming
关联一个
DOMHighResTimeStamp
`Critical-CH` 重启时间。
PerformanceNavigationTiming
关联一个
NotRestoredReasons
未恢复原因。
PerformanceNavigationTiming
关联一个
PerformanceTimingConfidence
置信值。
PerformanceNavigationTiming
关联一个实数
随机触发率
,由实现定义。
PerformanceNavigationTiming
关联一个 PerformanceTimingConfidenceValue
底层置信值
,由实现定义。
PerformanceNavigationTiming
关联一个 null 或 service worker 时序信息
service worker 时序。
unloadEventStart获取器步骤为返回 this 的 前文档卸载时序 的 unload 事件起始时间。
如果前一个文档和当前文档具有相同 源,此时间戳在 用户代理触发前文档unload 事件之前立即测量。若没有前文档或源不同,则返回 0。
unloadEventEnd 获取器步骤为返回 this 的 前文档卸载时序 的 unload 事件结束时间。
如果前一个文档和当前文档具有相同 源,此时间戳在 用户代理处理前文档unload 事件后立即测量。若没有前文档或源不同,则返回 0。
domInteractive获取器步骤为返回 this 的 文档加载时序的 DOM interactive 时间。
此时间戳在用户代理将 当前文档就绪状态设置为 "interactive"之前测量。
domContentLoadedEventStart获取器步骤为返回this的 文档加载时序的 DOM content loaded 事件起始时间。
此时间戳在用户代理分发 DOMContentLoaded 事件之前测量。
domContentLoadedEventEnd获取器步骤为返回 this 的 文档加载时序的 DOM content loaded 事件结束时间。
此时间戳在用户代理完成对 DOMContentLoaded 事件处理后测量。
domComplete获取器步骤为返回 this 的 文档加载时序的 DOM complete 时间。
此时间戳在用户代理将 当前文档就绪状态设置为 "complete"之前测量。详见文档就绪状态。
loadEventStart获取器步骤为返回 this 的 文档加载时序的 load 事件起始时间。
此时间戳在用户代理分发文档 load事件前测量。
loadEventEnd获取器步骤为返回 this 的 文档加载时序的 load 事件结束时间。
此时间戳在用户代理完成文档 load事件处理后测量。
type获取器步骤为运行 this 的 导航类型。
客户端重定向,如 Refresh pragma 指令,在本规范中不算作 HTTP 重定向。这种情况下, type 属性应返回适当值,如当前页重新加载则 reload,新 URL 导航则 navigate。
redirectCount获取器步骤为返回 this 的 重定向计数。
criticalCHRestart获取器步骤为返回 this 的 `Critical-CH` 重启时间。
如果 criticalCHRestart 不为 0,则它将在所有其他时间戳之前, 除 navigationStart、unloadEventStart 和 unloadEventEnd。 因为它标记了重定向部分重新启动的时刻。
notRestoredReasons获取器步骤为返回 this 的 未恢复原因。
confidence获取器步骤为执行下述步骤:
- 若 this 的 文档加载时序的 DOM interactive 时间为 0,返回 null。
- 若 this 的 置信值不为 null, 则返回它。
- 令 confidence 为新建
PerformanceTimingConfidence对象, 在this的 相关设置对象 的 相关域中创建。 - 设置 confidence 的
randomizedTriggerRate为 this 的 随机触发率。 -
设置 confidence 的
value,遵循如下算法:- 令 p 为 confidence 的
randomizedTriggerRate。 - 令 underlying 为 this 的 底层置信值,
一个
PerformanceTimingConfidenceValue。 - 令 r 为 [0, 1) 区间均匀随机抽选的实数。
- 如果 r ≥ p,返回 underlying。
- 否则:
- 令 p 为 confidence 的
- 返回 confidence。
这些值应只设置一次,且在 this 生命周期内不变。
本节旨在帮助 RUM 提供方和开发者解释
confidence。由于 随机触发率在不同记录间会变化,
需按记录加权以获得无偏聚合。下面流程说明如何在统计汇总前,根据 value
加权。
-
针对每个记录:
- 令 p 为记录的
randomizedTriggerRate。 - 令 c 为记录的
value。 - 令 R 为 c 是
high时取1,否则取0。 -
按 c 计算记录加权 w:
- 估算 high 均值时:w
= (R - (p / 2)) / (1 - p)。 - 估算 low 均值时:
w
= ((1 - R) - (p / 2)) / (1 - p)。
- 估算 high 均值时:w
- 令 weighted_duration =
duration* w。
- 令 p 为记录的
- 令 total_weighted_duration 为所有记录 weighted_duration 之和。
- 令 sum_weights 为所有记录 w 之和。
- 若sum_weights不近零,debiased_mean = total_weighted_duration / sum_weights。
- 按均值计算步骤求每条记录加权 w。
- 令 sum_weights 为所有记录 w 之和。
- 令 sorted_records 为所有记录按
duration升序排序。 - 欲求某分位(0-100),q
= percentile / 100.0 -
遍历sorted_records,对每条:
- 计算累计加权 cw:
cw
= sum_{i: duration_i <= duration_j} w_i。 - 无偏累计分布函数:
cdf
= cw / sum_weights
- 计算累计加权 cw:
cw
- 找到第一个 idx 满足 cdf ≥ q。
-
计算插值比例:
- 令 lower_cdf 为 sorted_records[idx-1] 的 cdf
- 令 upper_cdf 为 sorted_records[idx] 的 cdf
- 若 lower_cdf = upper_cdf,返回
duration,即 sorted_records[idx]。 - 否则:
toJSON()方法会为this执行默认toJSON步骤。
3.3.1.
NavigationTimingType
枚举
enum {NavigationTimingType ,"navigate" ,"reload" };"back_forward"
这些枚举值定义如下:
- navigate
- 导航,其 历史处理行为 被设置为 "default" 或 "replace"。
- reload
- 导航对象 navigable 被 重新加载。
- back_forward
- 从历史记录中应用的导航。
上述枚举值格式与 WebIDL 对枚举值的格式建议不一致。 但由于与已发布实现的兼容性问题,无法修改。[WebIDL]
3.3.2.
PerformanceTimingConfidence
接口
[Exposed =Window ]interface {PerformanceTimingConfidence readonly attribute double ;randomizedTriggerRate readonly attribute PerformanceTimingConfidenceValue ;value object (); };toJSON
- randomizedTriggerRate
-
该属性返回 [0, 1) 区间内的实数,表示暴露 置信
value时施加扰动的概率。 - value
- toJSON()
-
本方法为this 执行默认 toJSON 步骤。
3.3.3. PerformanceTimingConfidenceValue
枚举
enum {PerformanceTimingConfidenceValue ,"high" };"low"
这些枚举值定义如下:
- high
- 用户代理认为导航指标能够代表当前用户设备。
- low
- 导航指标可能不能代表当前用户设备。用户代理可能会考虑机器状态或用户配置。
在确定底层置信值时,用户代理 只能基于瞬时运行时条件作出判断,如启动、临时高 CPU 占用、临时内存压力或其他短时情形。
用户代理不得基于设备或配置的永久属性判定底层置信值。 禁止考虑的例子包括物理内存、CPU 核心数、已安装扩展数量等静态环境信息。
置信度旨在反映运行时的可变性,而非系统能力。
4. 流程
4.1. 处理模型
PerformanceNavigationTiming
接口定义的时序属性。带括号的属性代表涉及不同
源文档导航时可能不可用。
5. 创建导航时序条目
每个文档都关联一个导航时序条目,初始为未设值。
要为 Document
document
创建导航时序条目,
给定 fetch 时序信息 fetchTiming、数字
redirectCount、
NavigationTimingType
navigationType,null 或 service worker 时序信息 serviceWorkerTiming、
DOMString cacheMode、
DOMHighResTimeStamp
criticalCHRestart,以及 响应体信息
bodyInfo,依次执行:
- 令 global 为 document 的 相关全局对象。
- 令 navigationTimingEntry 为新建的
PerformanceNavigationTiming对象,分配在 global 的 realm 内。 - 为 navigationTimingEntry 执行资源时序条目设置,给定 "
navigation"、 document 的URL, fetchTiming、cacheMode 和 bodyInfo。 - 设置 navigationTimingEntry 的文档加载时序为document 的加载时序信息
- 设置 navigationTimingEntry 的前文档卸载时序 为 document 的前文档卸载时序。
- 设置 navigationTimingEntry 的重定向计数 为 redirectCount。
- 设置 navigationTimingEntry 的导航类型 为 navigationType。
- 设置 navigationTimingEntry 的service worker 时序 为 serviceWorkerTiming。
- 设置 document 的 导航时序条目为 navigationTimingEntry。
- 设置 navigationTimingEntry 的`Critical-CH` 重启时间 为 criticalCHRestart。
- 设置 navigationTimingEntry 的未恢复原因 为用 document 的未恢复原因创建 NotRestoredReasons 对象 的结果。
- 将 navigationTimingEntry 加入 global 的 performance entry buffer。
要为 Document
document排队导航时序条目,
排队 document 的
导航时序条目。
6. 隐私考量
本节为非规范内容。
6.1. 信息披露
利用精心设计的时序攻击,有泄露终端用户浏览和活动历史的风险。例如,卸载时间揭示了前一页执行其 unload 处理器的时长,可能被用于推测 用户登录状态。这类攻击通过卸载文档时强制执行 同源检测算法得到缓解,详见 HTML 规范。
放宽同源策略不足以阻止对其它文档的未授权访问。在共享托管环境里,不受信第三方可在同一 IP 不同端口部署 HTTP 服务器。
6.2. 跨目录访问
同一主机下不同页面(如用户内容平台中不同作者的页面)被认为属于同源, 因为没有机制可按路径名限制访问。页面间导航允许后续页面访问前一页的时序信息, 包括重定向和卸载事件等相关时序。
7. 安全考量
本节为非规范内容。
PerformanceNavigationTiming
接口会将前一个文档时序信息暴露给当前文档。
为限制包含前文档信息的 PerformanceNavigationTiming
属性的访问,
前文档卸载算法
会强制执行同源策略,
并将相关属性设为零。
7.1. 检测代理服务器
若用户代理与 Web 服务器之间部署有代理,
connectStart
到
connectEnd
的时间间隔反映用户代理与代理之间的延迟,而非 Web 服务器。
因此,Web 服务器有可能推断出代理的存在。对于 SOCKS 代理,该时间段还包含代理认证以及代理到 Web 服务器连接时间,这对代理探测有干扰。
若为 HTTP 代理,用户代理甚至可能完全无感知,因此无法总能防止该类攻击。
8. 废弃内容
本节定义了
[NAVIGATION-TIMING]
第一版中引入的属性和接口,仅为兼容性保留。作者不应再使用下列接口,强烈建议改用新的
PerformanceNavigationTiming
接口——参见变更及改进摘要。
8.1. PerformanceTiming 接口
[Exposed =Window ]interface {PerformanceTiming readonly attribute unsigned long long ;navigationStart readonly attribute unsigned long long ;unloadEventStart readonly attribute unsigned long long ;unloadEventEnd readonly attribute unsigned long long ;redirectStart readonly attribute unsigned long long ;redirectEnd readonly attribute unsigned long long ;fetchStart readonly attribute unsigned long long ;domainLookupStart readonly attribute unsigned long long ;domainLookupEnd readonly attribute unsigned long long ;connectStart readonly attribute unsigned long long ;connectEnd readonly attribute unsigned long long ;secureConnectionStart readonly attribute unsigned long long ;requestStart readonly attribute unsigned long long ;responseStart readonly attribute unsigned long long ;responseEnd readonly attribute unsigned long long ;domLoading readonly attribute unsigned long long ;domInteractive readonly attribute unsigned long long ;domContentLoadedEventStart readonly attribute unsigned long long ;domContentLoadedEventEnd readonly attribute unsigned long long ;domComplete readonly attribute unsigned long long ;loadEventStart readonly attribute unsigned long long ; [loadEventEnd Default ]object (); };toJSON
本节定义的所有时间值均以自 起的毫秒数计。
- navigationStart
-
本属性需返回用户代理完成提示卸载前一个文档后 的时间。如果没有前一个文档,则返回当前文档创建时的时间。
本属性未在
PerformanceNavigationTiming中定义。 开发者可通过timeOrigin获得等效的时间戳。 - unloadEventStart
-
如果前一个文档和当前文档属于同一 源, 则返回用户代理开始触发前文档 unload事件前的时间。 若无前文档或前文档非同源,则返回0。
- unloadEventEnd
-
如果前一个文档和当前文档同 源, 则返回用户代理完成前文档 unload事件处理后的时间。 若无前文档,源不同或卸载未完成,则返回0。
若导航发生HTTP 重定向且并非所有重定向都来自同一 源,
unloadEventStart和unloadEventEnd必须返回0。 - redirectStart
- redirectEnd
- fetchStart
-
若新资源通过 "GET" 请求方法 获取, fetchStart 返回用户代理开始检查 HTTP 缓存 前的时刻;否则返回开始获取资源的时间。
- domainLookupStart
-
返回用户代理开始对当前文档进行域名解析前的时刻。 若使用持久连接、或文档来自 HTTP 缓存 或本地资源,返回
fetchStart的值。 - domainLookupEnd
-
返回用户代理完成当前文档域名解析后的时刻。 若使用持久连接、或文档来自 HTTP 缓存 或本地资源,返回
fetchStart的值。检查与获取 HTTP 缓存内容也是获取流程的一部分。 由
requestStart、responseStart、responseEnd覆盖。若用户代理已在缓存中拥有域名信息,domainLookupStart 和 domainLookupEnd 分别为开始和结束从缓存获取域名数据的时刻。
- connectStart
-
返回用户代理开始与服务器建立连接以获取文档前的时刻。 若使用持久连接、文档来自 HTTP 缓存 或本地资源,返回
domainLookupEnd的值。 - connectEnd
-
返回用户代理完成与服务器建立连接,获取文档后的时刻。 若使用持久连接、文档来自 HTTP 缓存 或本地资源,返回
domainLookupEnd的值。如果传输连接失败,用户代理重新建立连接,则
connectStart和connectEnd应返回新连接的值。connectEnd包括建立传输连接的耗时,以及SSL握手、SOCKS认证等其它流程耗时。 - secureConnectionStart
-
该属性为可选。用户代理不支持时必须将其设为 undefined。若属性可用,且当前页的scheme [URL]为 "https",则返回 启动安全连接握手前的时刻。若可用但未用 HTTPS,则返回0。
- requestStart
-
返回用户代理向服务器、HTTP 缓存 或本地资源请求当前文档前的时刻。
若请求已发出后连接失败,用户代理重新建立连接并重发请求,
requestStart应返回新请求值。本接口未包含表示请求发送完成(如 requestEnd)的属性。
- 用户代理请求发送完成并不总能表示网络传输已结束, 拥有该属性的意义有限。
- 某些用户代理因 HTTP 层封装,确定请求实际完成时间成本较高。
- responseStart
-
返回用户代理收到服务器、HTTP 缓存 或本地资源首字节响应后的时刻。
- responseEnd
-
返回用户代理收到当前文档最后一个字节或传输连接关闭前的时刻,二者以先到为准。 文档可来源于服务器、HTTP 缓存或本地资源。
- domLoading
-
返回用户代理将当前文档就绪状态设置为 "loading"前的时刻。
由于不同用户代理创建 Document 对象的时机不同,
domLoading返回值具有实现依赖性,不应作为有效指标使用。 - domInteractive
-
返回用户代理将当前文档就绪状态设置为 "interactive"前的时刻。
- domContentLoadedEventStart
-
返回用户代理在
Document上触发DOMContentLoaded 事件 前的时刻。 - domContentLoadedEventEnd
-
返回文档DOMContentLoaded 事件完成后的时刻。
- domComplete
-
返回用户代理将当前文档就绪状态设置为 "complete"前的时刻。
若当前文档就绪状态 多次变为同一值,
domLoading、domInteractive、domContentLoadedEventStart、domContentLoadedEventEnd、domComplete均返回首次对应文档就绪状态变更的时间。 - loadEventStart
-
返回当前文档 load 事件触发前的时刻。尚未触发时返回0。
- loadEventEnd
-
返回当前文档 load 事件完成时的时间。尚未触发或未完成时返回0。
- toJSON()
- 按默认 toJSON 步骤在this上运行。
8.2. PerformanceNavigation 接口
[Exposed =Window ]interface {PerformanceNavigation const unsigned short = 0;TYPE_NAVIGATE const unsigned short = 1;TYPE_RELOAD const unsigned short = 2;TYPE_BACK_FORWARD const unsigned short = 255;TYPE_RESERVED readonly attribute unsigned short ;type readonly attribute unsigned short ; [redirectCount Default ]object (); };toJSON
- TYPE_NAVIGATE
- TYPE_RELOAD
- TYPE_BACK_FORWARD
-
导航,其 历史处理行为 被设置为 "entry update"。
- TYPE_RESERVED
-
上述未定义的任何导航类型。
- type
-
该属性返回上一次非重定向 导航的类型。 其值只可能为下列
navigation type定义之一。客户端重定向(如 Refresh 指令)不属于本规范下的HTTP 重定向。这类情形下,
type属性应返回合适值,如当前页刷新用TYPE_RELOAD,新 URL 导航用TYPE_NAVIGATE。 - redirectCount
-
该属性返回自上次非重定向导航以来的重定向次数。若无重定向,或有任何重定向非目标文档同源,返回0。
- toJSON()
- 按默认 toJSON 步骤在this上运行。
8.3.
对 Performance 接口的扩展
[Exposed =Window ]partial interface Performance { [SameObject ]readonly attribute PerformanceTiming ; [timing SameObject ]readonly attribute PerformanceNavigation ; };navigation
Performance 接口定义见 [PERFORMANCE-TIMELINE-2]。
- timing
-
timing属性表示自上次非重定向导航以来的时序信息。 该属性由PerformanceTiming接口定义。 - navigation
-
navigation属性由PerformanceNavigation接口定义。
9. 致谢
感谢 Anne Van Kesteren、Arvind Jain、Boris Zbarsky、Jason Weber、 Jonas Sicking、James Simonsen、Karen Anderson、Nic Jansma、Philippe Le Hegaret、Steve Souders、Todd Reifsteck、Tony Gentilcore、William Chan 和 Zhiheng Wang 对本规范的贡献。