阅读 244

前端性能分析 " Performance API "

定义

Performance 接口可以获取到当前页面中与性能相关的信息。它是 High Resolution Time API 的一部分,同时也融合了 Performance Timeline APINavigation Timing APIUser Timing APIResource Timing API

注意:除了以下指出的情况外,该接口及其成员在 Web Worker 中可用。此外,还需注意,performance 的创建和衡量都是同一环境下的。即,如果你在主线程(或者其他 worker)中创建了一个 performance,那么它在另外的 worker 线程中是不可用的;反之亦然。

Performance API
MDN Web docs描述
Resource Timing API获取和分析应用资源加载的详细网络计时数据
Navigation_timing_API提供了可用于衡量一个网站性能的数据
Performance支持应用程序中客户端的延时测量
Performance_Timeline提供了可用于衡量一个应用程序的客户端延时的数据
User_Timing_API允许开发者在浏览器性能时间线中创建针对特定应用的时间戳
Frame_Timing_API提供有关浏览器事件循环的帧计时数据
Network_Information_API可以获取到系统的网络连接信息,应用程序可以根据此信息为用户展现不同清晰度的内容
Navigation Timing: Processing Model
  1. Navigation Timing Level 1

timing-overview.png

  1. Navigation Timing Level 2

timestamp-diagram.svg

  • 上一个文档卸载
  • 重定向
  • 浏览器准备好使用http抓取文档
  • 检查本地缓存
  • 查询DNS域名
  • TCP建立连接
  • HTTP请求、响应
  • 渲染DOM树并解析
  • 网页开始加载资源
  • 准备就绪触发load事件执行回调函数

性能上报

DCA061F4-943D-4A4E-992F-7AE02E7D42AF.png

// onload事件触发 - 等待1s - 上报性能
var page = windows.performance.timing
dns = page.domainLookupEnd - page.domainLookupStart
tcp = page.connectEnd - page.connectStart
// 请求返回时长
connectTime = page.responseEnd - page.requestStart
// 服务端响应时长
responseTime = page.responseEnd - page.responseStart
domAnalysis = page.domComplete - page.domInteractive
// 页面白屏时长
whitePageTime = page.responseStart - page.navigationStart
// Dom渲染时长
domReady = page.domContentLoadedEventEnd - page.navigationStart
// 页面加载所需的总时长
allLoadTime = page.loadEventEnd - page.navigationStart
复制代码
PerformanceNavigation (将废弃)

属性

  1. redirectCount: 如果有重定向的话,页面通过几次重定向跳转而来
  2. type
type描述
0即 TYPE_NAVIGATENEXT 正常进入的页面(非刷新、非重定向等)
1即 TYPE_RELOAD 通过 window.location.reload() 刷新的页面
2即 TYPE_BACK_FORWARD 通过浏览器的前进后退按钮进入的页面(历史记录)
255即 TYPE_UNDEFINED 非以上方式进入的页面
方法
  1. Performance.getEntries()
  2. Performance.getEntriesByType()
  3. Performance.getEntriesByName()
  4. performance.now() 精准计算程序运行时间
mark、measures 计算程序时间
  1. performance.mark() 标记各种时间戳,进行打点
  2. performance.measure() 测量
  3. performance.clearMarks() 清除打点
  4. performance.clearMeasures() 清除测量数据
function randomFunc (n) {  
    if (!n) {
        // 生成一个随机数
        n = ~~(Math.random() * 10000);
    }
    var nameStart = 'markStart' + n; 
    var nameEnd   = 'markEnd' + n; 
    // 函数执行前做个标记
    window.performance.mark(nameStart);
 
    for (var i = 0; i < n; i++) {
        // do nothing
    }
 
    // 函数执行后再做个标记
    window.performance.mark(nameEnd);
 
    // 然后测量这个两个标记间的时间距离,并保存起来
    var name = 'measureRandomFunc' + n;
    window.performance.measure(name, nameStart, nameEnd);
}
 
// 执行三次看看
randomFunc();  
randomFunc();  
// 指定一个名字
randomFunc(888);

// 看下保存起来的标记 mark
window.performance.getEntriesByType('mark')

// 看下保存起来的测量 measure
window.performance.getEntriesByType('measure');

// 清除指定标记
window.performance.clearMarks('markStart888');  
// 清除所有标记
window.performance.clearMarks();
 
// 清除指定测量
window.performance.clearMeasures('measureRandomFunc');  
// 清除所有测量
window.performance.clearMeasures(); 


复制代码
Performance常见名词解释
  1. FP (First Paint) 首次绘制
  2. FCP (First Contentful Paint) 首次内容绘制
  3. LCP (Largest Contentful Paint) 最大内容渲染
  4. DCL (DomContentloaded)
  5. FMP(First Meaningful Paint) 首次有效绘制
  6. L (onLoad)
  7. TTI (Time to Interactive) 可交互时间
  8. TBT (Total Blocking Time) 页面阻塞总时长
  9. FID (First Input Delay) 首次输入延迟
  10. CLS (Cumulative Layout Shift) 累积布局偏移
  11. SI (Speed Index)
FPS 计算(检测页面是否卡顿)
// FPS检测
(() => {
    const limit = 3;                        // 出现低FPS的连续次数上限
    const below = 20;                       // 可容忍的最低FPS
    let count = 0;
    let lastTime = performance.now();
    let frame = 0;
    let lastFameTime = performance.now();
    let fps = 0;
    
    const loop = () => {
        frame += 1;
        const now = performance.now();
        const fs = (now - lastFameTime);
        lastFameTime = now;
        
        // 1000毫秒的 FPS (不需要也是可以的,看你选择)
        fps = Math.round(1000 / fs);
        
        if (now > 1000 + lastTime) {
            // 1s 时间段的FPS
            fps = Math.round((frame * 1000) / (now - lastTime));
            frame = 0;
            lastTime = now;
        }
        if (fps < below) {
            count += 1;
            if (count >= limit) {
                console.log('网页卡顿', `连续${count}次FPS低于${below},当前FPS为${fps}`);
                BUS.trigger('fps-low');    // 关闭一些JS动画
            }
        } else {
            count = 0;
        }
        window.requestAnimationFrame(loop);
    };

    loop();
})();
复制代码
参考文章
  1. 初探 performance – 监控网页与程序性能
  2. 获取页面加载各个阶段所需时间
  3. Navigation Timing Level 2
文章分类
前端
文章标签