专栏首页陈泽钦的专栏页面性能优化的利器 — Timeline
原创

页面性能优化的利器 — Timeline

作者介绍:陈泽钦,腾讯移动客户端工程师,目前就职于腾讯MIG移动互联网事业群,负责腾讯浏览服务TBS的X5内核业务。

1. 网页渲染的基础

在前面整理的Chrome官方的渲染性能优化文章中,讲述到了网页生成过程中,主要包含如下几个步骤:

* JavaScript。一般来说,我们会使用JavaScript来实现一些视觉变化的效果。比如用jQuery的animate函数做一个动画、对一个数据集进行排序、或者往页面里添加一些DOM元素等。当然,除了JavaScript,还有其他一些常用方法也可以实现视觉变化效果,比如:CSS Animations, Transitions和Web Animation API。

* 计算样式。这个过程是根据CSS选择器,比如.headline.nav > .nav_item,对每个DOM元素匹配对应的CSS样式。这一步结束之后,就确定了每个DOM元素上该应用什么CSS样式规则。

* 布局。上一步确定了每个DOM元素的样式规则,这一步就是具体计算每个DOM元素最终在屏幕上显示的大小和位置。web页面中元素的布局是相对的,因此一个元素的布局发生变化,会联动地引发其他元素的布局发生变化。比如,元素的宽度的变化会影响其子元素的宽度,其子元素宽度的变化也会继续对其孙子元素产生影响。因此对于浏览器来说,布局过程是经常发生的。

* 绘制。绘制,本质上就是填充像素的过程。包括绘制文字、颜色、图像、边框和阴影等,也就是一个DOM元素所有的可视效果。一般来说,这个绘制过程是在多个层上完成的。

* 渲染层合并。由上一步可知,对页面中DOM元素的绘制是在多个层上进行的。在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上。对于有位置重叠的元素的页面,这个过程尤其重要,因为一旦图层的合并顺序出错,将会导致元素显示异常。

参考tikizheng在Timeline的入门篇中所整理的框图,更清晰地展示了页面生成的流程。

网页中的重绘过程是影响整体性能下降的关键点之一,因而网站开发者应该更多地去避免在站点中进行不必要以及不适时的重绘步骤,借助Inspector中的Timeline面板可以很好地剖析这一些存在的问题。

2. 实例讲解

在此,本文将通过一个简单的网页Demo来讲述Timeline的常用技巧

Demo页面,具体如下:


<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>X5 CORE</title>
    <style type="text/css">
        body { font-size: 16px }
        p { font-weight: bold }
        span { color: red }
        p span { display: none }
        img { width: 100%; max-width: 300px }
    </style>

    <script>
      function a_click() {
        var span = document.getElementsByTagName('span')[0];
        span.textContent = 'Web performance'; // change DOM text content, lead to relayout
        span.style.color = 'green';  // change CSSOM property
      }
    </script>
  </head>

  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="X5.jpg" onclick="a_click()"></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline';  // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var div = document.createElement('div');
      div.textContent = '*** Add new element to DOM ***';
      div.style.color = 'blue';
      document.body.appendChild(div);
    </script>
  </body>
</html>

这是一个很简单的网页,展示了一行文字和图片,而在body中有一段script对个别元素进行样式和内容的调整;此外还有一个点击事件,即点击图片后,会再次执行一段修改元素内容和样式的脚本。

2.1 操作流程:

  • Ctrl+E 开始录制
  • 刷新页面
  • 点击图片,执行onclick事件
  • Ctrl+E 结束录制

操作完毕后,Inspector在Timeline中记录了这一过程中,与页面相关的各项信息。

可以看到下图中上方的两个红色框位置,该区域是Timeline面板的整体预览区,分了三部分(FPS、CPU、NET)来展示,具体可查看Timeline使用详情。首个红色框位置,记录了首次加载页面时,所经历的Loading -> Scripting -> Rendering -> Painting流程。而右边的红色框区域中,可见CPU中首先显示了黄色(代表Scripting)的峰形区域,随后显示了紫色(代表Rendering)的峰形区域,表示了页面在响应点击事件后所进行的流程。

2.2 事件详解:

通过滚轮在Flame框图中,可以对页面中的事件进行缩放,可已清晰地观察到在首次加载过程中,所经历的Loading -> Script -> Layout -> Paint -> Composite Layers等流程。

并且,在点击了各个事件之后,下方的Summary中会罗列出更加具体的信息。比如,点击Evaluate Script事件后,可以查看总共的耗时,并且可以链接到具体的JS源代码:

而在网页加载完毕后,对图片进行了点击操作,触发了<img />标签的onclick事件,开发者能够在Flame框图中查看到点击事件中各个流程,其展现了所有的JS调用栈

系统Event(click) ==> <img />绑定的onclick事件(html中第24行) ==> function a_click() (html中第14行)

2.3 综合分析

由此可见,当在页面已经得到生成了之后,利用JS去更改个别元素的内容(DOM结构变化),或者是调整元素属性(CSSOM属性变化),都会引起页面重新进行Rendering -> Painting流程。如果这些是不必要的操作,则必定会导致网页性能降低。

因此,对于开发者来说,应该要知道如何去定位网页中发生重绘的区域

3. 定位网页中发生重绘的区域

开启方式:在控制栏的右上角属性按钮中,选择More tools — Rendering settings,然后在弹出的面板中选择 Paint Flashing

如下图中的操作,在勾选了Paint Flashing后,还是在Demo页面中,点击图片触发JS事件,进而会span标签的内容以及颜色,而在页面预览区域中,可以观察到该行文本在刷新内容过程中,有绿色的方框进行高亮包围,说明了这一部分区域发生了重新绘制

另外一个重要的现象是,虽然点击后的JS事件仅修改了<span>的内容,但是重绘却发生在整一个<p>标签中,说明了个别元素的重新绘制,一般会影响到父元素或者是周围的元素,造成区域性重绘,因此在页面中避免不必要的重绘显得至关重要。

小技巧: 当发现页面中,如果存在一些不必要的重绘现象,而又不能够定位到具体的原因,可以对该区域中的各个元素,依次进行隐藏(在Element面板中设置visibility:hidden),观察效果来定位。

4. 显示composited layer的边界

More tools — Rendering settings中,还可以开启 Layer Borders,观察页面中的各个区域绘制情况。通过这一项功能,开发者能够发现页面中发生动画或者是CSS transforms/transitions等发生了形状或位置变化的元素,进而优化其渲染时间

Demo页面比较简单所以效果不明显,利用官方图片来展示Layer Borders的效果:

5. 在Paint Profiler中查看绘制细节

当在Flame框图中点击了 一个Paint事件,则会在详情面板中出现一个Paint专有标签:Paint Profiler

通过Paint Profiler面板,开发者可以知道该次Paint事件的绘制时间、绘制位置和大小等信息,并且能够具体到某一个元素的绘制耗时:当拖动标尺,直至内容框中仅有目标元素Image的绘制时,即可观察到其耗时(0.14ms/0.2ms),以及图片区域的大小、位置等等信息。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Selenium WebDriver找不到元素的三种情况

    原因:页面被刷新了。 在当前页面找不到这个元素了,但是你自己手动复制到页面开发者工具上查看明明有啊,为啥在代码里面就找不到了呢?这时,你还可能会问“可是明明元...

    软测小生
  • 从0到1开发测试平台(三)利用vue cli创建前端vue项目

    去node官网https://nodejs.org/zh-cn/下载node安装包进行安装

    cctester
  • 【JS应用】Iframe 解决跨域

    跨域的东西, 简直不要接触太多,网上相关内容一抓一大把,但是突然学习到一个关于前端解决跨域的方式

    神仙朱
  • 营销渠道的经典效果评估方法

    一维评估方法就是指标评估法,通过一个指标去评估渠道流量的价值,可以将指标做从数量上、质量上和核心交互上去划分:

    GA小站
  • 熊市建仓的最佳策略

    最近听了一遍三九的深圳跨年分享的视频录播,巩固一下自己的区块链投资策略,把几个要点写下来,防止手贱乱操作。

    申龙斌
  • 【前沿】TensorFlow Pytorch Keras代码实现深度学习大神Hinton NIPS2017 Capsule论文

    【导读】10月26日,深度学习元老Hinton的NIPS2017 Capsule论文《Dynamic Routing Between Capsules》终于在a...

    WZEARW
  • 【前沿】TensorFlow Pytorch Keras代码实现深度学习大神Hinton NIPS2017 Capsule论文

    【新智元导读】10月26日,深度学习元老Hinton的NIPS2017 Capsule论文《Dynamic Routing Between Capsules》终...

    新智元
  • C++程序控制结构

    case 后面没break 就会一直执行下去的,所以break是为了跳出switch。比如:

    ppjun
  • Java核心技术卷2 高级特性 学习笔记(3)

    文档头之后通常是文档类型定义(Document Type Definition,DTD),文档类型定义时确保文档正确的一个重要机制,但是它不是必须的。

  • 无需3D运动数据训练,最新人体姿势估计方法达到SOTA | CVPR 2020

    人体的运动对于理解人的行为是非常重要的。尽管目前已经在单图像3D姿势和动作估计方面取得了进展,但由于缺少用于训练的真实的3D运动数据,因此现有的基于视频的SOT...

    AI科技大本营

扫码关注云+社区

领取腾讯云代金券