Jex
性能优化

性能优化

permance 看event loop

灰色:宏任务;
橙色:浏览器内部函数;
紫色:回流和重绘;
渲染:绿色;
parse HTML:蓝色;
其他颜色都是用户的代码;
微任务:run Microtask,属于宏任务中的一部分;

performer 宽度代表执行时间,长度代表调用栈的深度(特别长的可能存在递归),每一帧(60HZ,16.7ms)都会有一个渲染的宏任务(长任务除外)。

常见网站性能指标

  1. FP 白屏(First Paint Time ): 从页面开始加载到浏览器中检测到渲染(任何渲染)时被触发(例如背景改变,样式应用等)
  2. FCP 首屏(first contentful paint ):从页面开始加载到页面内容的任何部分呈现在屏幕上的时间。 (关注的焦点是内容,这个度量可以知道用户什么时候收到有用的信息(文本,图像等))
  3. FMP 首次有效绘制(First Meaningful Paint ): 表示页面的“主要内容”,开始出现在屏幕上的时间点,这项指标因页面逻辑而异,因此上不存在任何规范。(只是记录了加载体验的最开始。如果页面显示的是启动图片或者 loading 动画,这个时刻对用用户而言没有意义)
  4. LCP(Largest Contentful Paint ):LCP 指标代表的是视窗最大可见图片或者文本块的渲染时间
  5. 长任务(Long Task):当一个任务执行时间超过 50ms 时消耗到的任务 (50ms 阈值是从 RAIL 模型总结出来的结论,这个是 google 研究用户感知得出的结论,类似用户的感知/耐心的阈值,超过这个阈值的任务,用户会感知到页面的卡顿)
  6. TTI (Time To Internative):从页面开始到它的主要子资源加载到能够快速地响应用户输入的时间。(没有耗时长任务)
  7. 首次输入延时 FID (first Input Delay):从用户第一次与页面交互到浏览器实际能够开始处理事件的时间。(点击,输入,按键)
  8. 总阻塞时间 TBT(total blocking time ): 衡量从 FCP 到 TTI 之间主线程被阻塞时长的总和。
  9. DCL (DOMContentLoaded):当 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式,图像和子框架的完成加载。
  10. L(onLoaded):当依赖的资源,全部加载完毕之后才会触发
  11. CLS(Cumulative Layout Shift): 是所有布局偏移分数的汇总,凡是在页面完整生命周期内预料之外的布局偏移都包括。布局偏移发生在任意时间,当一个可见元素改变了它的位置,从一个渲染帧到下一个

核心指标

  • LCP 显示最大内容元素所需时间 (衡量网站初次载入速度)
  • FID 首次输入延迟时间 (衡量网站互动顺畅程度)
  • CLS 累计版面配置移转 (衡量网页元件视觉稳定性)



测试方法

Performance API

Performance 是一个浏览器全局对象,提供了一组 API 用于编程式地获取程序在某些节点的性能数据。它包含一组高精度时间定义,以及配套的相关方法。我们可以直接在浏览器控制台打印window.performance 结果如下:

// 获取 performance 数据
var performance = {
    // memory 是非标准属性,只在 Chrome 有
    // 我有多少内存
    memory: {
        usedJSHeapSize:  16100000, // JS 对象(包括V8引擎内部对象)占用的内存,一定小于 totalJSHeapSize
        totalJSHeapSize: 35100000, // 可使用的内存
        jsHeapSizeLimit: 793000000 // 内存大小限制
    },

    // 我从哪里来?
    navigation: {
        redirectCount: 0, // 如果有重定向的话,页面通过几次重定向跳转而来
        type: 0           // 0   即 TYPE_NAVIGATENEXT 正常进入的页面(非刷新、非重定向等)
                          // 1   即 TYPE_RELOAD       通过 window.location.reload() 刷新的页面
                          // 2   即 TYPE_BACK_FORWARD 通过浏览器的前进后退按钮进入的页面(历史记录)
                          // 255 即 TYPE_UNDEFINED    非以上方式进入的页面
    },
//  核心时间相关
    timing: {
        // 在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload 的时间戳,如果无前一个网页 unload ,则与 fetchStart 值相等
        navigationStart: 1441112691935,

        // 前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0
        unloadEventStart: 0,

        // 和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳
        unloadEventEnd: 0,

        // 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0
        redirectStart: 0,

        // 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0
        redirectEnd: 0,

        // 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
        fetchStart: 1441112692155,

        // DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
        domainLookupStart: 1441112692155,

        // DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
        domainLookupEnd: 1441112692155,

        // HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等
        // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间
        connectStart: 1441112692155,

        // HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等
        // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间
        // 注意这里握手结束,包括安全连接建立完成、SOCKS 授权通过
        connectEnd: 1441112692155,

        // HTTPS 连接开始的时间,如果不是安全连接,则值为 0
        secureConnectionStart: 0,

        // HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存
        // 连接错误重连时,这里显示的也是新建立连接的时间
        requestStart: 1441112692158,

        // HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
        responseStart: 1441112692686,

        // HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
        responseEnd: 1441112692687,

        // 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件
        domLoading: 1441112692690,

        // 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件
        // 注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源
        domInteractive: 1441112693093,

        // DOM 解析完成后,网页内资源加载开始的时间
        // 在 DOMContentLoaded 事件抛出前发生
        domContentLoadedEventStart: 1441112693093,

        // DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)
        domContentLoadedEventEnd: 1441112693101,

        // DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件
        domComplete: 1441112693214,

        // load 事件发送给文档,也即 load 回调函数开始执行的时间
        // 注意如果没有绑定 load 事件,值为 0
        loadEventStart: 1441112693214,

        // load 事件的回调函数执行完毕的时间
        loadEventEnd: 1441112693215

        // 按照字母排序
        // connectEnd: 1441112692155,
        // connectStart: 1441112692155,
        // domComplete: 1441112693214,
        // domContentLoadedEventEnd: 1441112693101,
        // domContentLoadedEventStart: 1441112693093,
        // domInteractive: 1441112693093,
        // domLoading: 1441112692690,
        // domainLookupEnd: 1441112692155,
        // domainLookupStart: 1441112692155,
        // fetchStart: 1441112692155,
        // loadEventEnd: 1441112693215,
        // loadEventStart: 1441112693214,
        // navigationStart: 1441112691935,
        // redirectEnd: 0,
        // redirectStart: 0,
        // requestStart: 1441112692158,
        // responseEnd: 1441112692687,
        // responseStart: 1441112692686,
        // secureConnectionStart: 0,
        // unloadEventEnd: 0,
        // unloadEventStart: 0
    }
}

咱们不慌 先来一张图解释下页面加载的几个关键时刻

Google performance 面板

整体结构

我们第一眼可能会被这些花花绿绿的色块吓到 咱们别怕 一点点带大家分析
从上到下分别为 4 个区域
1:工具条,包含录制,刷新页面分析,清除结果等一系列操作
2:总览图,高度概括随时间线的变动,包括 FPS,CPU,NET
3:火焰图,从不同的角度分析框选区域 。例如:Network,Frames, Interactions, Main 等
4:总体报告:精确到毫秒级的分析,以及按调用层级,事件分类的整理

工具条区域


上面红框从左到右 咱们把鼠标放上去可以看到几个英文单词

  • record 记录浏览器运行中的某一个时间段的表现
  • reload page 用于记录网页从最开始的加载到所有资源加载完成这个过程的性能表现。点击之后,页面会自动重新加载
  • Screenshots 屏幕快照,显示动态加载的页面图片
  • memory 查看多种内存占用变化

现在我们可以打开任意一个网站 点击第二个按钮 reload page 开始分析

总览区域


1. FPS: 全称 Frames Per Second,表示每秒传输帧数,是速度单位,用来分析动画的一个主要性能指标。1fps = 0.304 meter/sec(米/秒)。如上图所示,绿色竖线越高,FPS 越高。 红色表示长时间帧,可能出现卡顿掉帧。
不同帧的体验

  • 帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;
  • 帧率在 30 ~ 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异;
  • 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感; 帧率波动很大的动画,亦会使人感觉到卡顿。

2. CPU:CPU 资源。此面积图指示消耗 CPU 资源的事件类型。 图中颜色分别为(与总体报告中的 Summary 颜色数据表示一致):

  • 蓝色(Loading):表示网络通信和 HTML 解析时间。
  • 黄色(Scripting):表示 JavaScript 执行时间。
  • 紫色(Rendering):表示样式计算和布局(重排)时间。
  • 绿色(Painting):表示重绘时间。
  • 灰色(other):表示其它事件花费的时间。
  • 白色(Idle):表示空闲时间。

3. NET:每条彩色横杠表示一种资源。横杠越长,检索资源所需的时间越长。 每个横杠的浅色部分表示等待时间(从请求资源到第一个字节下载完成的时间)

火焰图

4.Main:记录了渲染进程中主线程的执行记录,点击 main 可以看到某个任务执行的具体情况 是我们分析具体函数耗时最常看的面板:
首先,面板中会有很多的 Task,如果是耗时长的 Task,其右上角会标红,这个时候,我们可以选中标红的 Task,然后放大,看其具体的耗时点。
放大后,这里可以看到都在做哪些操作,哪些函数耗时了多少,这里代码有压缩,看到的是压缩后的函数名。然后我们点击一下某个函数,在面板最下面,就会出现代码的信息,是哪个函数,耗时多少,在哪个文件上的第几行等。
这样我们就很方便地定位到耗时函数 然后去针对性优化

总体报告

Summary:表示各指标时间占用统计报表


这里的颜色代表的意思和总览区域里面的 cpu颜色一样的意思 大家不清楚的可以往上翻一下

这里一般来说,需要着重关注的有两个:一是黄色的区域,代表脚本执行时间,另一个是紫色的渲染时间