前端优化-渲染优化

前端优化其六-开发60帧每秒的app

浏览器如果花费很长的时间去绘制一帧的话,就会丢失另一帧。最糕的情况下,浏览器会直接卡死。

浏览器如何渲染帧

  1. 浏览器向服务器发起get请求 get/http/1.1
  2. 服务器做出响应并发送html
  3. 浏览器提前解析dom(parse html)
  4. 浏览器解析cssom (parse stylesheet)
  5. 结合 dom + cssom生成render tree (Recalculate styles)
  6. 浏览器开始计算布局,即计算元素会占用多少空间、位置(layout),网络布局意味着某个元素可以影响其他元素,这对浏览器来说非常复杂。例如body的宽度会影响子项的宽度,一直向dom树的下方蔓延。
  7. 从矢量到光栅,把像素绘制到图层(paint)
  8. 浏览器需要把图像解码成内存,篇4说过,这很消耗内存和cpu(image decode)
  9. 合成图层,浏览器会把内容绘制到一或多个图层上,图层太多或者太少都可能影响性能。或许你可以想像一下photoshop图层,他们很像。 举个例子:
    making frame

javascript/css引起的渲染

经常,我们使用javascript操作dom、style,引起网页外观变化;或许我们也有一个css动画、过渡造成网页外观变化,可能会触发浏览器做一些工作。

javascript/css ==> style ==> layout ==> paint ==> composite

通过css/javascript 造成外观变化,浏览器需要重新计算受影响元素的样式。这些样式可能会导致浏览器重新计算布局。在布局完成后重新绘制。最后合成图层

javascript/css ==> style ==> paint ==> composite

这一回我们又改观了我们的界面。很幸运在浏览器重新计算受影响元素的样式后,并不需要重新布局,浏览器将直接绘制新的内容,最后合成图层

javascript/css ==> style ==> composite

我们的开发人员花废了一些心思,这次改变外观没有引起重绘,更没有引起重新布局。浏览器重新合成图层就合适。遗憾的是,目前只有opacity、transform两个css属性才不会引起重绘与重布局。这也是为何transform动画性能会远远高于left、top、bottom、right等旧动画属性的原因。

LIAR和四个时间点

webapp的生命周期的四大领域称为 RAIL(Response、animation、idle、load)。

  • load 任何时候我们都应该加快加载速度,最好不要超过1s.
  • idle 当 load 完成,等待用户操作的这断时间称为闲置时间(idle),可以在这段时间里处理我们为了加快加载速度而延后的操作。通常,这些闲置时段时长大约为50ms,也可能是一段连续的idle。比如:我们有一个app应用,有一个查看联系人列表功能。如果我们在idle里直接加载渲染好了,用户秒开是不是很酷。
  • response load完成之后,我们也好好的利用了idle。现在用户将与网页互动,网页需要做出回应。有研究表明,如果用户在进行某项操作(如点击按钮),网页能在100ms之内做出响应,那么用户就不会发现任何延迟。需要在这段时间内对所有用户操作做出回应。
  • animation 如果用户的操作需要实现动画效果,需要达到60fps。例如手指滑过时响应的动画。60fps意味着每帧我们仅有16ms的处理时间,事实上因为浏览器还有其他自己要做的事情,比如gc,我们往往只有10ms左右。达到60fps并不容易,一不小心就触发了性能问题,想想上边渲染一帧浏览器所需要的工作,10ms好像显得十分不够用。

合理的利用LIAR的各个时间点对渲染性能十分重要 L(1000ms)、I(50ms)、R(100ms)、A(16ms)。

backwards

利用浏览器在完成了初始的工作并运行动画后,可以较低的成本向后运行动画。相当于提前计算任务繁重的工作。

  1. first 收获所有元素初始信息
  2. last 展开元素,收集所有元素动画结束信息
  3. invest 计算差异,保存差异。
  4. play 动画开始

搜集所有信息可能听着需要花费许多时间。还记得上面说的100ms的延时响应吗?只要在这断时间内完成,那么用户将不会感知,我们的动画顺便爬到了60fps。最后,在动画回退时,还可以按原路径返回,好像又节省了一些时间。

最后

我们能够浏览器绘制或布局甚至运行javascript,这并不表明我们拥有无限的时间预算。例如布局和绘制时间都会取决于受影响的元素数量,或者我们可以通过减少受影的元素数量来提升性能。