分析运行时性能

October 20, 2021

原文:Analyze runtime performance
作者:MSEdgeTeammikehoffmsDanishOnGitjm-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 面板查看更多的相关信息。如果这个样式改变花了太长时间,那这就是一个性能问题。如果这个样式计算影响了很多元素,那这就有可改进的空间。

rendering-tools-performance-recalculate-style-summary.msft

为了减少 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。
过多的元素的提升,大大影响了动画的性能。 谨慎地提升图层,只有当你知道它提供了切实的改进时才会提升。

相关阅读


Profile picture

这里是要没时间了

职业是前端开发,早餐喜欢吃 711 的芝士猪排饭团。喜欢写代码,爱折腾

© 2021, 分享知识和生活,记录成长与感动。