Copyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范定义了一个接口,通过允许 Web 开发者访问高精度时间戳,帮助他们测量其应用程序的性能。
本节描述本文档在其发布时的状态。当前 W3C 出版物的列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。
本 User Timing 规范旨在取代 [USER-TIMING-2],并包括:
本文档由 Web Performance Working Group 作为候选推荐草案发布,使用的是 推荐标准轨道。
作为候选推荐发布并不 意味着 W3C 及其成员的认可。候选 推荐草案整合了工作组 打算纳入后续候选推荐快照的、相对于前一候选推荐所作的变更。
这是一份草案文档,随时可能被更新、替换或废弃并由其他 文档取代。不应将本文档作为进行中的工作以外的内容来引用。
本文档由一个按照 W3C 专利 政策运作的小组制作。 W3C 维护一份 任何专利 披露的公开列表, 这些披露与该小组的交付成果相关;该页面还包括 披露专利的说明。实际 知悉某项专利,且认为该专利包含 必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露相关信息。
本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。
本节是非规范性的。
Web 开发者需要能够评估和理解其
应用程序的性能特征。虽然 JavaScript [ECMA-262] 提供了一种测量
应用程序延迟的机制(从 Date.now() 方法取得当前时间戳),但该
时间戳的精度会因用户代理而异。
本文档定义了 PerformanceMark 和 PerformanceMeasure 接口,以及对
Performance 接口的扩展,它们公开高
精度、单调递增的时间戳,使开发者能够更好地测量其应用程序的性能
特征。
下面的脚本展示了开发者如何使用本文档定义的接口来获得 与开发者脚本相关的计时数据。
async function run() {
performance.mark("startTask1");
await doTask1(); // 一些开发者代码
performance.mark("endTask1");
performance.mark("startTask2");
await doTask2(); // 一些开发者代码
performance.mark("endTask2");
// 将它们记录出来
const entries = performance.getEntriesByType("mark");
for (const entry of entries) {
console.table(entry.toJSON());
}
}
run();
[PERFORMANCE-TIMELINE-2] 定义了两种
可用于检索已记录指标的机制:getEntries()
和 getEntriesByType() 方法,以及
PerformanceObserver 接口。前者最适合
你想要在某个单一时间点按名称检索特定指标的场景,
后者则针对你可能希望在新指标变得
可用时接收通知的场景进行了优化。
再举一个例子,假设有一个元素,当它被 点击时,会获取一些新内容并指示该内容已获取完成。 我们想要报告从用户点击到获取 完成之间的时间。我们不能标记点击处理程序执行的时间,因为那样 会漏掉处理事件的延迟,所以我们改用事件的 硬件时间戳。我们还想知道组件名称,以便获得 更详细的分析数据。
element.addEventListener("click", e => {
const component = getComponent(element);
fetch(component.url).then(() => {
element.textContent = "Updated";
const updateMark = performance.mark("update_component", {
detail: {component: component.name},
});
performance.measure("click_to_update_component", {
detail: {component: component.name},
start: e.timeStamp,
end: updateMark.startTime,
});
});
});
除标记为非规范性的章节外,本规范中的所有编写指南、图示、示例和注释都是 非规范性的。本规范中的其他所有内容都是规范性的。
本文档中的关键词 MAY 和 MUST 在且仅在它们如这里所示以全大写形式出现时, 应按 BCP 14 [RFC2119] [RFC8174] 中所描述的方式解释。
某些一致性要求以对属性、 方法或对象的要求来表述。这些要求应解释为 对用户代理的要求。
本规范中的 IDL 片段 MUST 按 Web IDL 规范中关于一致性 IDL 片段的描述来解释。 [WEBIDL]
Performance
接口的扩展
Performance 接口和
DOMHighResTimeStamp
定义于 [HR-TIME-2]。
PerformanceEntry
接口定义于 [PERFORMANCE-TIMELINE-2]。
WebIDLdictionary PerformanceMarkOptions {
any detail;
DOMHighResTimeStamp startTime;
};
dictionary PerformanceMeasureOptions {
any detail;
(DOMString or DOMHighResTimeStamp) start;
DOMHighResTimeStamp duration;
(DOMString or DOMHighResTimeStamp) end;
};
partial interface Performance {
PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {});
undefined clearMarks(optional DOMString markName);
PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark);
undefined clearMeasures(optional DOMString measureName);
};
存储带有关联名称的时间戳(一个“mark”)。它 MUST 运行这些 步骤:
detailstartTime移除带有关联名称的已存储时间戳。它 MUST 运行这些 步骤:
PerformanceMark
对象中移除所有位于 performance
entry buffer 中的对象。PerformanceMark 对象中列在 performance
entry buffer 中且其 name 是 markName 的所有对象。存储两个标记之间的 DOMHighResTimeStamp
持续时间,并附带关联名称(一个“measure”)。它 MUST 运行这些步骤:
PerformanceMeasureOptions
对象,并且 start、end、duration 和 detail 中至少有一个 存在,则运行以下
检查:
PerformanceMeasureOptions
对象,并且如果其 end 成员 存在,
则令 end time 为传入 startOrMeasureOptions 的 end 运行 convert a mark to a timestamp
算法所返回的值。PerformanceMeasureOptions
对象,并且如果其 start 和 duration
成员都 存在:
start
运行 convert a mark to a
timestamp 算法所返回的值。
duration
运行 convert a mark to a
timestamp 算法所返回的值。
Performance 对象的 now()
方法将会返回的值。
PerformanceMeasureOptions
对象,并且如果其 start 成员 存在,
则令 start time 为传入 startOrMeasureOptions 的 start 运行 convert a mark to a timestamp
算法所返回的值。PerformanceMeasureOptions
对象,并且如果其 duration 和
end 成员都
存在:
duration
运行 convert a mark to a
timestamp 算法所返回的值。
end 运行 convert a mark to a
timestamp 算法所返回的值。DOMString,则令
start time 为传入 startOrMeasureOptions 运行 convert a mark to a timestamp
算法所返回的值。
0。PerformanceMeasure 对象
(entry)。name 属性设置为 measureName。entryType 属性设置为 DOMString "measure"。
startTime 属性设置为 start time。duration 属性设置为从 start
time 到 end time 的持续时间。所得持续时间值 MAY
为负数。detail 属性:
PerformanceMeasureOptions
对象,并且 startOrMeasureOptions 的 detail 成员
存在:
detail
调用 StructuredSerialize
算法的结果。
detail 设置为
以 record 和 当前
realm 调用 StructuredDeserialize
算法的结果。null。detailstartdurationend移除带有关联名称的已存储时间戳。它 MUST 运行这些步骤:
PerformanceMeasure 对象中位于 performance
entry buffer 中的所有对象。PerformanceMeasure 对象中列在
performance
entry buffer 中且其 name 是 measureName 的所有对象。
PerformanceMark 接口还会将通过 Performance 接口的 mark() 方法创建的标记暴露给 Performance
Timeline。
WebIDL[Exposed=(Window,Worker)]
interface PerformanceMark : PerformanceEntry {
constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {});
readonly attribute any detail;
};
PerformanceMark 接口扩展了 PerformanceEntry
接口的以下属性:
name 属性必须返回该标记的名称。
entryType 属性必须返回 DOMString "mark"。
startTime 属性必须返回一个 DOMHighResTimeStamp,
其值为该标记的时间值。
duration 属性必须返回值为 0 的 DOMHighResTimeStamp
。
PerformanceMark 接口包含以下
附加属性:
detail
属性必须返回其被设置为的值(它是从 PerformanceMarkOptions 字典复制而来的)。
PerformanceMark 构造器
PerformanceMark 构造器必须运行 以下步骤:
Window 对象,并且 markName 使用了与
PerformanceTiming
接口中的某个只读属性相同的名称,
则抛出一个 SyntaxError。
PerformanceMark 对象
(entry)。
name 属性设置为 markName。entryType 属性设置为 DOMString "mark"。startTime 属性:
duration 属性设置为 0。detail 为 null,则将
entry 的 detail 设置为
null。
detail 调用 StructuredSerialize
算法的结果。detail 设置为
以 record 和 当前
realm 调用 StructuredDeserialize
算法的结果。PerformanceMeasure 接口还会将
通过 Performance 接口的 measure() 方法创建的度量暴露给 Performance Timeline。
WebIDL[Exposed=(Window,Worker)]
interface PerformanceMeasure : PerformanceEntry {
readonly attribute any detail;
};
PerformanceMeasure 接口扩展了
PerformanceEntry
接口的以下属性:
name 属性必须返回该度量的名称。
entryType 属性必须返回 DOMString
"measure"。
startTime 属性必须返回一个 DOMHighResTimeStamp,
其值为该度量的开始标记。
duration 属性必须返回一个 DOMHighResTimeStamp,
其值为该度量的持续时间。
PerformanceMeasure 接口包含
以下附加属性:
detail 属性必须返回其被设置为的值(它是
从 PerformanceMeasureOptions 字典复制而来的)。
实现 User Timing API 的用户代理需要在
supportedEntryTypes 中包含 "mark" 和
"measure"。这允许开发者检测对 User Timing 的支持。
要将标记转换为时间戳,给定一个作为
DOMString 或 DOMHighResTimeStamp
的 mark,运行这些步骤:
DOMString,并且它与
PerformanceTiming
接口中的某个只读属性同名,则令 end time 为在
name 设置为 mark 的值时运行 convert a name to a timestamp 算法
所返回的值。
DOMString,则令 end time 为
performance
entry buffer 中其 name 是 mark 的 PerformanceMark 对象的最近一次出现中的
startTime 属性值。如果未找到匹配项,则抛出一个 SyntaxError。
DOMHighResTimeStamp:
TypeError。
要将名称转换为 时间戳,
给定一个作为
PerformanceTiming
接口中的只读
属性的 name,运行这些步骤:
Window 对象,则抛出一个 TypeError。navigationStart,则返回 0。PerformanceTiming
接口中 navigationStart 的值。
PerformanceTiming
接口中 name 的值。
0,则抛出一个
InvalidAccessError。
PerformanceTiming 接口定义于 [NAVIGATION-TIMING],并且 现在被视为已废弃。支持使用来自 PerformanceTiming 接口的名称,是为了保持向后兼容,但未来没有计划将此 功能扩展到 [NAVIGATION-TIMING-2] 中定义的 PerformanceNavigationTiming 接口(或其他接口)中的名称。
鼓励开发者使用以下推荐的标记名称来 标记常见计时。用户 代理不会验证这些名称的使用是否 适当或是否与其描述一致。
添加此类推荐的标记名称可以帮助性能 工具为站点定制指导。这些标记名称还可以帮助真实用户 监控提供商和用户代理大规模收集有关其应用程序性能的 Web 开发者信号,并在不需要任何站点特定工作的情况下将此信息呈现给 开发者。
在此示例中,页面在加载时异步初始化聊天小部件、 搜索框和新闻源。完成后, "mark_fully_loaded" 标记名称使实验室工具 和分析 提供商能够自动显示该计时。
window.addEventListener("load", (event) => {
Promise.all([
loadChatWidget(),
initializeSearchAutocomplete(),
initializeNewsfeed()]).then(() => {
performance.mark('mark_fully_loaded');
});
});
detail
元数据可以包含关于该功能的任何有用信息,包括:
在此示例中,FancyJavaScriptFramework 的 ImageOptimizationComponent 用于按最佳性能调整图像大小。代码记录 此功能的使用情况,以便实验室工具和分析能够衡量 它是否帮助提升了性能。
performance.mark('mark_feature_usage', {
'detail': {
'feature': 'ImageOptimizationComponent',
'framework': 'FancyJavaScriptFramework'
}
})
本节是非规范性的。
本规范定义的接口会暴露页面中特定 JavaScript 活动的、可能 敏感的计时信息。有关暴露 高分辨率计时信息的隐私和安全注意事项,请参见 [HR-TIME-2]。
由于 Web 平台的设计遵循这样一个不变原则:页面中包含的任何 脚本都与同一页面中包含的任何其他脚本具有相同的访问权限, 无论这些脚本的源如何, 本规范定义的接口不会对 已记录计时信息的记录或检索施加任何限制——也就是说,页面中包含的任何脚本记录的 user timing mark 或 measure,都可以被 同一页面上运行的任何其他脚本读取,而不论其源如何。
感谢 James Simonsen、 Jason Weber、 Nic Jansma、 Philippe Le Hegaret、 Karen Anderson、 Steve Souders、 Sigbjorn Vik、 Todd Reifsteck 和 Tony Gentilcore 对此工作的贡献。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: