原文:Analyze runtime performance
作者:MSEdgeTeam,mikehoffms,DanishOnGit,jm-trd-ms。
用户往往都期待页面是可交互且丝滑流畅的,而像素管道(pixel pipeline)中的每一个阶段都有可能导致卡顿(jank)。本文帮助你学习如何识别和修复常见的可能导致运行时性能问题,以及相关的工具。
概述
- 不要写强制浏览器重新计算布局的 JavaScript。分离读和写函数,并且优先执行读操作。
- 不要让你的 CSS 过于复杂。使用更少的 CSS 并且保持你的 CSS 选择器简单。
- 尽可能避免浏览器布局操作(layout),选择使用那些完全不会触发布局的 CSS。
- 绘制(painting)可能比任何其他的渲染活动花上更多的时间。注意绘制瓶颈。
JavaScript
JavaScript 计算,尤其是触发昂贵的视觉变化的那种,可能会拖慢应用的性能。不要让时机不恰当或长时间运行的 JavaScript 干扰用户的交互。
JavaScript:工具
使用 Performance 工具录制,找出运行时间长得离谱的执行脚本(Evaluate Script)
事件。
如果你发现你的 JavaScript 执行过程频繁卡顿(渲染的中断),你可能需要更进一步地分析并且收集一份 JavaScript CPU 概况(profiles)。CPU 概况展示了页面中函数的运行时间花费在了哪里。你可以在Speed up JavaScript runtime中学习怎样创建 CPU 概况。
JavaScript:问题
下面这个表格描述了一些常见的 JavaScript 问题和可能的方法。
问题 | 例子 | 解决方法 |
---|---|---|
昂贵的输入处理程序影响页面响应和动画。 | 触摸,视差滚动 | 让浏览器去处理触摸和滚动,或者尽量推迟事件监听器的绑定。 推荐阅读文章 Expensive Input Handlers in Paul Lewis’ runtime performance checklist |
时机不恰当的 JavaScript 影响页面响应,动画,和加载 | 用户在页面加载完成后向右滚动,setTimeout / setInterval。 | 使用 JavaScript 运行时:用 requestAnimationFrame 将 DOM 操作分散到各帧中,使用 Web Workers |
长时间运行的 JavaScript 影响页面响应 | 太多的 JS 工作导致 DOMContentLoaded 事件被延迟 | 把单纯的计算工作移至 Web Workers。如果你需要访问 DOM,那就使用 requestAnimationFrame 。 |
垃圾脚本影响页面响应或者动画 | 垃圾收集可能发生在任何地方 | 写更少的垃圾脚本,推荐阅读文章 Garbage Collection in Animation in Paul Lewis’ runtime performance checklist。 |
样式
改变样式的开销也很大,尤其是当这些改变影响多个 DOM 中的元素的时候。当你对一个元素应用样式时,浏览器会计算出所有相关元素的影响,重新计算布局并重新绘制。
样式:工具
使用 Performance 工具做记录,检查大型的 Recalculate Style
事件(紫色显示)。
选择一个 Recalculate Style
事件,在 Details 面板查看更多的相关信息。如果这个样式改变花了太长时间,那这就是一个性能问题。如果这个样式计算影响了很多元素,那这就有可改进的空间。
为了减少 Recalculate Style
事件的影响:
- 使用 CSS Triggers 来了解哪些 CSS 属性会触发布局,绘制,和合成。这些属性对渲染性能的影响最大。
- 换成影响较小的属性。
样式:问题
下面这个表格描述了一些常见的样式问题和可能的方法。
问题 | 例子 | 解决方法 |
---|---|---|
昂贵的样式计算影响页面响应和动画。 | 任何改变元素形状的 CSS 属性,比如宽度,高度,或者位置;浏览器会检查其他所有的元素并且重新计算布局。 | 避免触发布局的 CSS |
复杂的选择器计算影响页面响应和动画。 | 嵌套选择器迫使浏览器了解所有其他元素的一切,包括父元素和子元素。 | 在你的CSS中用 class 引用一个元素 |
布局
布局(在 Firefox 中又称重排)是浏览器计算页面中所有元素的位置和尺寸的过程。web 的布局模型意味着元素之间可能会互相影响;例如 <body>
元素的宽度通常会影响它的任何子元素的宽度,以此类推,从树上一直向下。对于浏览器来说,这个过程可能相当复杂。
根据经验来说,如果你在一帧完成之前要求 DOM 返回一个几何属性的值,你会发现你触发了 “强制同步布局”,如果经常重复对大型 DOM 树执行的话,这将是一个很大的性能瓶颈。
布局:工具
占位
布局:问题
下面这个表格描述了一些常见的布局问题和可能的方法。
问题 | 例子 | 解决方法 |
---|---|---|
强制同步布局影响页面响应和动画。 | 强制浏览器在像素管道中过早地执行布局,导致渲染过程中的重复步骤。 | 先批量读取样式,然后再进行样式的任何写入 |
布局抖动影响页面响应和动画。 | 一个将浏览器置于读-写-读-写循环的循环语句会迫使浏览器一遍又一遍地重新计算布局。 | 使用 FastDom 库自动进行批量读写操作。 |
绘制和合成(Paint and composite)
绘制是填充像素的过程。它往往是渲染过程中性能花销最大的部分。如果你注意到你的页面没有达到设计的效果,那很可能是你的绘制部分出了问题。
合成是将页面上的绘画部分放在一起在屏幕上显示的地方。在大多数情况下,如果你坚持只使用合成器属性而完全避免绘制,这会给为你的页面带来性能的重大改善,但你需要当心层数过多。
绘制和合成:工具
想知道绘制需要多长时间或绘制发生的频率吗?勾选 Performance 面板中的启用高级绘制仪器(Enable advanced paint instrumentation)设置,然后进行录制。如果你的大部分渲染时间都花在了绘制上,你就有绘制问题了。
绘制和合成:问题
下面这个表格描述了一些常见的绘制和合成问题和可能的方法。
问题 | 例子 | 解决方法 |
---|---|---|
绘制风暴影响页面响应和动画。 | 大的绘制区域,或者昂贵的绘制影响页面响应和动画。 | 避免绘制,将正在移动的元素提升到自己的层,使用 transform 和 opacity。 |
过多的元素的提升,大大影响了动画的性能。 | 谨慎地提升图层,只有当你知道它提供了切实的改进时才会提升。 |