介绍
Performance timeline ,
w3c 有两个版本的规范,本文基于 第二版本 介绍。
工欲善其事,必先利其器
。要想使页面更快,那么准确测量出性能数据也是很重要的。
我们来看一下,在一个web页面的生命周期之内,我们基于 Performance Timeline
可以得到哪些性能指标。
主要分为以下三大类:
navigation-timing
:navigation of the documentresource-timing
:页面资源user-timing
:开发者自定义的一些监控, 主要是(mark 和 measure,下文会讲)
举个🌰, w3c 上的例子,我稍加改造 :
<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
<script>
function init() {
// see [[USER-TIMING-2]]
performance.mark("startWork");
setTimeout(() => {
performance.mark("endWork");
measurePerf();
}, 2000);
}
function measurePerf() {
performance
.getEntries()
.map(entry => JSON.stringify(entry, null, 2))
.forEach(json => console.log(json));
}
引入了一个 外部图片,
mark
可以理解为标记了一个时间点
getEntries
得到所有的性能数据,最后输出。
具体结果可看:
{
"name": "",
"entryType": "navigation",
"startTime": 0,
"duration": 50.07500003557652,
}
{
"name": "https://www.w3.org/Icons/w3c_main.png",
"entryType": "resource",
}
{
"name": "startWork",
"entryType": "mark",
"startTime": 49.990000028628856,
"duration": 0
}
{
"name": "first-paint",
"entryType": "paint",
"startTime": 94.83499999623746,
"duration": 0
}
{
"name": "first-contentful-paint",
"entryType": "paint",
"startTime": 94.83499999623746,
"duration": 0
}
{
"name": "endWork",
"entryType": "mark",
"startTime": 2050.5150000099093,
"duration": 0
}
由此我就得到了页面上,当时的所有性能指标,包括navigation
, resource
, FP
, FCP
...等一些自定义的指标。
ps:
FP
:页面上第一个像素落点的时候FCP
: 页面上开始有内容绘制的时候
现在我想要过滤一下只要我自己 mark 的点,
可采用:getEntriesByType(mark)
,
只想要页面绘制相关的 fp,fcp,
采用 getEntriesByName('first-paint')
。
but,我们得到的就只是当时得到的性能指标,假如后面又有 图片请求了呢,又有 js 请求了呢 🤣🤣。
我们要一直 轮询我们的 measurePerf
吗?
当然有新的解决方式。
PerformanceObserver
PerformanceObserver,是浏览器内部对Performance实现的观察者模式,即: 当有性能数据产生时,主动通知你。
这解决了我们之前的问题:
- 重复轮训
- 轮巡时不断判断,这个数据是新产生的,还是以前的
- 可能其他数据的消费者也需要操作数据
监测页面FP,FCP
现在可以:
// 定义一个观察者
const observer = new PerformanceObserver(list => {
list.getEntries().forEach((entry) => {
console.log('entry对象', entry);
});
});
// 观察的类型
observer.observe({
entryTypes: ['paint']
});
关于 entryTypes
, 可以取如下值:
- frame:event-loop 时的每一帧
- navigation:导航
- resource:资源
- mark: 打点,得到一个时间戳
- measure:在两个点之间测量
- paint:绘制
- longtask(好像只有 chrome支持):任何在浏览器中执行超过 50 ms 的任务,都是 long task
关于 entry
:
每个事件类型的 entry 对象都不一样。
navigation
entry 对象里能拿到相关的数据有

这里完整地描述了一个 页面
呈现的完整流程。
拿到每个时间点可以进行分析每个区间的时间耗费。
let t = entry
console.log('DNS查询耗时 :' + (t.domainLookupEnd - t.domainLookupStart).toFixed(0))
console.log('TCP链接耗时 :' + (t.connectEnd - t.connectStart).toFixed(0))
console.log('request请求耗时 :' + (t.responseEnd - t.responseStart).toFixed(0))
console.log('解析dom树耗时 :' + (t.domComplete - t.domInteractive).toFixed(0))
console.log('白屏时间 :' + (t.responseStart - t.navigationStart).toFixed(0))
console.log('domready时间 :' + (t.domContentLoadedEventEnd - t.navigationStart).toFixed(0))
console.log('onload时间 :' + (t.loadEventEnd - t.navigationStart).toFixed(0))
resource
entry 对象里能拿到相关的数据有

这里道理和上面的 navigation
一样。
mark
这里打了四个点,用来标识两个任务的开始时间和结束时间,两个任务分别采用 Promise
推迟执行。doTask
模拟推迟行为。
const doTask = (ms) => new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ms);
})
async function run() {
performance.mark("startTask1");
await doTask(1000); // Some developer code
performance.mark("endTask1");
performance.mark("startTask2");
await doTask(2000); // Some developer code
performance.mark("endTask2");
// Log them out
const entries = performance.getEntriesByType("mark");
for (const entry of entries) {
console.table(entry.toJSON());
}
}
run();
分别得到四个点的时间。

measure
用于在两个 **点 (即上文提到的打点) ** 之间测量时间
举个 例子:需要测量一个 for
循环花费的时间。
const observer = new PerformanceObserver(list => {
list.getEntries().forEach((entry) => {
console.table(entry);
});
});
observer.observe({
entryTypes: ['measure']
});
performance.mark('cal-start');
// 模拟耗时任务
for(let i = 0; i < 10000; i ++) {
}
performance.mark('cal-end');
// 该 measure 的名字:my-cal
// measure 开始的时间点:cal-start
// measure 结束的时间点:cal-end
performance.measure('my-cal', 'cal-start', 'cal-end')

longtask
这个 支持度 好像不高,chrome 亲测可以。 可以检测 应用里 任何在浏览器中执行超过 50 ms 的任务。
原因来源还比较多:
- 浏览器的render
- 自身的js执行
比如上面得 实例, 我们仅需加入一个需要的检测 的 entryType
既可。
observer.observe({
entryTypes: ['measure', 'longtask']
});
可以看到,Performance timeline 第二版本,相对以前还是有很大改进的,我们也有了更多的手段得到想要监控的数据。 EOF。
参考
最后
如果喜欢本篇文章,可以关注的微信公众号,如果不嫌烦,还可以把它添加到桌面😀。
search.png
