前端性能之Performance API

375 阅读4分钟

Performance

Performance 接口可用于获取当前页面中与性能相关的信息。开发者可以使用 Performance API 来抓取和分析当前网页的性能数据。它主要用于读取以前发生的事件和性能测量。

关键API

PerformanceNavigationTiming

PerformanceNavigationTiming 提供了用于存储和检索有关浏览器文档事件的指标的方法和属性。例如,此接口可用于确定加载或卸载文档需要多少时间。

各个指标

阶段名计算方式计算的意义
RedirectredirectEnd - redirectStart计算重定向的持续时间,如 URL 重定向的延迟。
Service Worker InitworkerStart - startTime计算 Service Worker 启动的时间。
Service Worker Fetch EventfetchStart - workerStart计算从 Service Worker 初始化到开始抓取资源之间的时间。
HTTP CachefetchStart - fetchStart表示 HTTP 缓存命中情况的计算指标。
DNSdomainLookupEnd - domainLookupStart计算 DNS 查询的持续时间。
TCPconnectEnd - connectStart计算 TCP 连接的建立时间。
TLSsecureConnectionStart - connectStart计算安全连接的建立时间(仅在使用 HTTPS 时)。
QUICconnectEnd - connectStart计算 QUIC 连接建立时间(图中未明确列出)。
RequestrequestStart - fetchStart计算请求启动到资源抓取的时间。
Early HintsfirstInterimResponseStart - requestStart计算从请求开始到接收初始响应之间的时间。
ResponseresponseEnd - responseStart计算接收到响应的时间。
ProcessingloadEventEnd - responseEnd计算响应处理完成后到页面完全加载的时间。
LoadloadEventEnd - loadEventStart计算加载事件初始和结束的时间。
DOM InteractivedomInteractive - fetchStart计算从开始请求到 DOM 交互准备的时间。
DOM Content LoadeddomContentLoadedEventEnd - domContentLoadedEventStart计算 DOM 内容加载事件的持续时间。
DOM CompletedomComplete - domContentLoadedEventEnd计算从 DOM 内容加载完毕到 DOM 全部资源加载完成的时间。
Unload EventunloadEventEnd - unloadEventStart计算 unload 事件的持续时间。
// 等待页面加载完成后执行
window.onload = function() {
    // 获取导航性能数据
    const navigationEntries = performance.getEntriesByType('navigation');

    if (navigationEntries.length > 0) {
        const navData = navigationEntries[0]; // 获取第一个(最近的)导航条目

        // 计算和输出性能指标
        const performanceMetrics = {
            navigationStart: navData.startTime, // 页面导航开始时间
            redirectTime: navData.redirectEnd - navData.redirectStart, // 重定向时间
            appCacheTime: navData.fetchStart - navData.domainLookupEnd, // 应用缓存时间
            dnsLookupTime: navData.domainLookupEnd - navData.domainLookupStart, // DNS 查询时间
            tcpConnectionTime: navData.connectEnd - navData.connectStart, // TCP 连接时间
            tlsTime: navData.secureConnectionStart - navData.connectStart, // TLS 建立时间
            requestStartTime: navData.requestStart, // 请求开始时间
            responseProcessingTime: navData.responseEnd - navData.responseStart, // 响应处理时间
            domInteractiveTime: navData.domInteractive, // DOM 交互时间
            domContentLoadedTime: navData.domContentLoadedEventEnd - navData.domContentLoadedEventStart, // DOM 内容加载时间
            loadEventDuration: navData.loadEventEnd - navData.loadEventStart // 加载事件持续时间
        };

        // 输出结果
        console.table(performanceMetrics);
    } else {
        console.log('No navigation entries found.');
    }
};

// navigationStart	0
// redirectTime	0
// appCacheTime	-4.799999997019768
// dnsLookupTime	0
// tcpConnectionTime	517
// tlsTime	256.20000000298023
// requestStartTime	523.5999999940395
// responseProcessingTime	9.599999994039536
// domInteractiveTime	805.2000000029802
// domContentLoadedTime	0
// loadEventDuration	0

PerformanceResourceTiming

PerformanceResourceTiming 接口可以检索和分析有关加载应用程序资源的详细网络计时数据。应用程序可以使用 timing 指标来确定获取特定资源所需的时间长度,例如XMLHttpRequest,image 或 script。

// 获取所有资源的性能数据
const resourceEntries = performance.getEntriesByType('resource');

// 循环输出每个资源的性能数据
resourceEntries.forEach((entry) => {
    console.log('Resource Name:', entry.name);
    console.log('Start Time:', entry.startTime);
    console.log('Duration:', entry.duration);
    console.log('DNS Lookup Time:', entry.domainLookupEnd - entry.domainLookupStart);
    console.log('TCP Connection Time:', entry.connectEnd - entry.connectStart);
    console.log('Response Time:', entry.responseEnd - entry.responseStart);
    console.log('---------------------------');
});

// 例如:
// Resource Name: https://gw.alipayobjects.com/zos/antfincdn/nc7Fc0XBg5/8a6844f5-a6ed-4630-9177-4fa5d0b7dd47.png
// Start Time: 1486.3000000044703
// Duration: 5.699999995529652
// DNS Lookup Time: 0
// TCP Connection Time: 0
// Response Time: 1.7999999970197678

PerformancePaintTiming

PerformancePaintTiming 是一个提供页面在构建过程中的“绘制”(也称“渲染”)时间点信息的接口。“绘制”是指将渲染树转换为页面上像素的过程。

// 获取绘制条目的性能数据
const paintEntries = performance.getEntriesByType('paint');

// 遍历每个绘制条目并输出信息
paintEntries.forEach((entry) => {
    console.log('Paint Name:', entry.name);
    console.log('Start Time:', entry.startTime);
    // Duration for paint typically is 0
    console.log('Duration:', entry.duration); 
    console.log('---------------------------');
});

// Paint Name: first-paint
// Start Time: 940.6999999880791
// Duration: 0
// ---------------------------
// Paint Name: first-contentful-paint
// Start Time: 940.6999999880791
// Duration: 0

PerformanceMarkPerformanceMeasure

PerformanceMark是一个用来标记特定事件的功能。你可以在代码中为关键事件添加标记,从而为后续的性能分析提供上下文。

PerformanceMeasure是用来定义一个性能度量指标,它基于你设置的标记来计算几个时间点之间的时间差。

// 开始标记
performance.mark('startRendering');

// 模拟一些渲染工作
setTimeout(() => {
    // 结束标记
    performance.mark('endRendering');

    // 定义测量  measure(measureName, startMark, endMark) || measure(measureName, measureOptions)
    performance.measure('renderingDuration', 'startRendering', 'endRendering');

    // 获取并输出测量结果
    const measures = performance.getEntriesByName('renderingDuration');
    console.log('Rendering Duration:', measures[0].duration, 'ms');

    // 可选:清理
    performance.clearMarks('startRendering');
    performance.clearMarks('endRendering');
    performance.clearMeasures('renderingDuration');
}, 1000); // 模拟渲染延迟

// Rendering Duration: 1002.0999999940395 ms

PerformanceObserver

PerformanceObserver 用于监测性能度量事件,主要用于实时监控网页的性能事件并收集数据。在事件触发时,回调函数将会被调用,开发者可以在函数中处理这些事件。

var observer = new PerformanceObserver(function (list, obj) {
  var entries = list.getEntries();
  for (var i = 0; i < entries.length; i++) {
    // Process "mark" and "frame" events
  }
});
observer.observe({ entryTypes: ["mark", "frame"] });

function perf_observer(list, observer) {
  // Process the "measure" event
}
var observer2 = new PerformanceObserver(perf_observer);
observer2.observe({ entryTypes: ["measure"] });