笔记:《Rendering, repaint, reflow/relayout, restyle》中的例子,在现代浏览器


前言

  1. updated:2017-06-26,替换上传错了的图。
  2. updated:2017-06-25 这里推荐一篇最近翻到的文章:《浏览器渲染详细过程:重绘、重排和composite只是冰山一角》
  3. updated:2017-05-15,将截图替换成了 Chrome 中 inspector 的 performance tab 中对应的数据截图(估计下次更新我就直接在这里写句「这篇文章已经过时」)。
  4. 原文写作的时间得出数据总结结论都是为了帮助开发者理解浏览器内部做了什么,发生了什么。这篇笔记的由来也是想自己动手试一试,看一下数据。

虽然自己截了不少图,这里数据意义个人觉得并不是非常充分,即使最后确实看到了 Layout 耗时比只有 paint 确实要多,但浏览器的发展已经经历了很多变化,这个程度的测量(measurement)可能完全跟不上时代。

笔记由来是读了《Rendering:repaint, reflow/relayout, restyle》(翻译在此)之后,想自己使用 modern browser 来试一试的心情。

原文中给的两个测试:第一个是 restyle.html,第二个是 relayout.html,文件地址暂时看来没有必要自己再做一份,用的还是原作者自己网站上的 host 地址。

在 Chrome 中

目前 Chrome 中用来检测的已经不是检查器中 Timeline 视图,更新成了 Performance 视图。具体的使用方法不做赘述,可以参考 Google Developer 中心的相关文档:地址

restyle.html 测试

首先是第一个测试,也就是通过:

  1. 改变一个样式,立即读取样式信息;
  2. 将需要改变的样式全部完成变化之后,统一查询信息。

两种方式来观察。restyle 测试的完整截图,如下图,红框部分剪头指向的部分就是我操作的四次点击(原作者测试中是点击了两次,每次间隔两秒)。

改变一个样式,立即读取样式信息;

通过鼠标可以在 timeline 部分滑出一个区间(官方文档中的 portion),下面的 main thread activity 对应的部分会对这部分内容进行详细显示,如下图粉红色部分所示:

在点击事件发生了的时候,原作者给出的 restyle.html 中其实是做的事情如下:

function touch(){
  bodystyle.color = 'red';
  //bodystyle.padding = '1px';
  tmp = computed.backgroundColor;
  bodystyle.color = 'white';
  //bodystyle.padding = '2px';
  tmp = computed.backgroundImage;
  bodystyle.color = 'green';
  //bodystyle.padding = '3px';
  tmp = computed.backgroundAttachment;
}

点击时间发生之后,浏览器发生了的事情在上图中所标出:

  1. Event Click;
  2. Update Layer Tree;
  3. Paint;
  4. Composite Layer Tree。

和正常概念里中描述的步骤 (js 修改 DOM 结构或样式 -> 计算 style -> layout 重排、布局)-> paint 绘制 -> composite 合成)对比,少了一步 layout 重排布局。

点击 paint 的绿色色块,下方的 summary 会显示详情。

Paint summary 截图


将需要改变的样式全部完成变化之后,统一查询信息

原作者在这一步所做的:

function touchlast() {
  bodystyle.color = 'yellow';
  //bodystyle.padding = '4px';
  bodystyle.color = 'pink';
  //bodystyle.padding = '5px';
  bodystyle.color = 'blue';
  //bodystyle.padding = '6px';

  tmp = computed.backgroundColor;
  tmp = computed.backgroundImage;
  tmp = computed.backgroundAttachment;
}

Paint summary 截图

relayout.html 测试

思路上面的一致,但是修改了会影响元素布局的样式属性 padding 的值。

  • 改变一个样式,立即读取样式信息;
  • 将需要改变的样式全部完成变化之后,统一查询信息。

点击时间发生之后,浏览器发生了的事情在上图中所标出:

  1. Event Click;
  2. Layout;
  3. Update Layer Tree;
  4. Paint;
  5. Composite Layer Tree;
  6. Update Layer Tree。

每次修改样式之后,立即计算

原作者在这里所做的:

function touch(){
  bodystyle.color = 'red';
  bodystyle.padding = '1px';
  tmp = computed.backgroundColor;
  bodystyle.color = 'white';
  bodystyle.padding = '2px';
  tmp = computed.backgroundImage;
  bodystyle.color = 'green';
  bodystyle.padding = '3px';
  tmp = computed.backgroundAttachment;
}

Layout summary 截图

Update Layer Tree summary 截图

Paint summary 截图:


修改了所有样式之后,再统一计算

原作者在这里所做的:

function touchlast() {
  bodystyle.color = 'yellow';
  bodystyle.padding = '4px';
  bodystyle.color = 'pink';
  bodystyle.padding = '5px';
  bodystyle.color = 'blue';
  bodystyle.padding = '6px';

  tmp = computed.backgroundColor;
  tmp = computed.backgroundImage;
  tmp = computed.backgroundAttachment;
}

Layout summary 截图

Update Layer Tree summary 截图

Paint summary 截图


这里只贴出部分数据图,剩下的可以加载提供的 performance profile 文件进行查看。观察数据,在有relayout 被触发的时候,会紧跟上一个 Update Layer Tree,而且两者的耗时都比只有 Paint 的时间要大很多。(一个对比,Layout 本身耗时:0.12 ms,之后紧跟的 Update Layer Tree 的耗时:0.12 ms,和 Paint 耗时:60 μs)。

感谢阅读

你们好, 2018 年初把小站从 Jekyll 迁移到 Hugo 的过程中,删除了评论区放的 Disqus 插件,考虑有二:首先无论评论、还是对笔记内容的进一步讨论,读者们更喜欢通过邮件、或者 Twitter 私信的方式来沟通;其次一年多以来 Disqus 后台能看到几乎都是垃圾留言(spam),所以这里直接贴一下邮件、以及 Twitter 账户 地址。

技术发展迭代很快,所以这些笔记内容也有类似新闻的时效性,不免有过时、或者错误的地方,欢迎指正 ^_^。

BEST
Lien(A.K.A 胡椒)
本站总访问量 本站总访客量 本文总阅读量