harttle/harttle.github.io

2017/08/15/browser-render-frame

utterances-bot opened this issue · 7 comments

浏览器的 16ms 渲染帧 | Harttle Land

由于现在广泛使用的屏幕都有固定的刷新率(比如最新的一般在 60Hz),在两次硬件刷新之间浏览器进行两次重绘是没有意义的只会消耗性能。浏览器会利用这个间隔 16ms(1000ms/60)适当地对绘制进行节流,因此 16ms 就成为页面渲染优化的一个关键...

https://harttle.land/2017/08/15/browser-render-frame.html

言简意赅,棒

感谢作者分享。有个疑问,浏览器会一直处与重新render或者准备render的状态吗,耗时任务阻塞后续的render造成卡顿,首先要这个任务里有触发render的操作吧。还有最后说的事件处理处在同一个tick指的是什么意思呢?意思是onprogress的callback会一直占用js的excute context导致这一轮的tick一直卡着吗?

layout和paint任务是浏览器调度的,有些JS API操作可以强制浏览器立即进行layout。渲染性能相关可以参考:https://developers.google.com/web/fundamentals/performance/rendering/

JavaScript的一个特征是run to the end,同步的一套代码一定会从头跑到尾,整个进程才能开始响应新的事件。所以只要前面有while(true),后续的microtask、task队列(layout、paint在这里)都会被阻塞。这两个队列的调度细节可以参考这篇: https://harttle.land/2019/01/16/how-eventloop-affects-rendering.html

那如果在task里没有去主动触发layout的操作,浏览器还会进行16ms的刷新吗?这个时候的耗时task造成的卡顿,指的是页面uninteractive而不是画面显示卡顿吧?

这篇文章我也拜读过。这边把页面渲染划分到了task任务里,但是whatwg的eventloop规范里一次tick是包括task microtask render(需要的情况下),这边的render和你说的页面渲染是一个吗?

如果存在一个任务在 16ms 内未能执行结束,页面就会掉帧给人卡顿的感觉

这边说的意思理解起来就是浏览器每时每刻都在进行16ms的刷新操作,只要耗时任务开始了,就阻塞了。不知可是这样?

那如果在task里没有去主动触发layout的操作,浏览器还会进行16ms的刷新吗?

如果有dom改动、css改动,在下一个脚本执行之前浏览器一定会做layout(否则脚本读到的dom跟此前设置的就不一致了)。 是否做 paint 有很多策略甚至还会去计算独立的子集去只渲染个别元素:https://blog.chromium.org/2017/01/performance-improvements-in-chromes.html

这个时候的耗时task造成的卡顿,指的是页面uninteractive而不是画面显示卡顿吧?

根据经典的浏览器实现讲,页面也会卡顿。因为 paint 和 点击、网络、layout 这些都在一个 task 队列里。前面的会卡住后面的,16ms内paint没执行到就会丢帧,丢帧的感受就是画面卡。但 chrome 有一个 urgent task 的概念来优化,把 paint task 提前:

Starting in Chrome 41, we've created a task scheduler integrated into the Blink rendering engine. The scheduler is capable of evaluating pending tasks and reordering them so that the most urgent tasks. 参考 https://blog.chromium.org/2015/04/scheduling-tasks-intelligently-for_30.html

这边的render和你说的页面渲染是一个吗?

不一样。"render"、”渲染“这样的词很有歧义。microtask render 指的应该是执行 microtask;本文的render指的是DOM树最终paint出来,包括layout+paint(其实还有composite)

只要耗时任务开始了,就阻塞了。不知可是这样?

是。但现在的浏览器不会不停地刷新,会检查是否需要刷新

感谢大佬耐心解答。
不过还是有个疑惑点。浏览器的帧刷新是不是每秒都一直在进行呢,就好像显示器一样?对于task的划分,看起来就只要不是那几种的micro,就全都是macro,所以就会有前面的耗时长导致后面的卡?

16ms内paint没执行到就会丢帧

js里如果不涉及到dom的操作,就没有layout了吧,还会有paint卡顿吗?(也就是浏览器是不是会一直保持刷新)

您好,一直不理解 requestAnimationFrame 这个和宏任务微任务的联系。我理解的事件循环执行顺序如下:
微任务=> GUI 渲染 => 宏任务,requestAnimationFrame 应该属于 GUI 部分吧,但是 setTimeout 和 requestAnimationFrame 的执行顺序并不能确认,大部分情况的运行结果是 setTimeout 先执行,能否对这里做个解读啊?