浏览器的每一帧

1,380 阅读3分钟

渲染进程中的线程

image.png

从图中可以看到浏览器渲染页面主要涉及到两个进程:

Renderer Process: 在这个进程中,会创建一个完整的帧,帧结束之后,会被推送到Gpu进程中
Gpu process: 根据提交的帧的信息,会将数据转换为实际的像素绘制到屏幕上面,GPU进程中只存在一个单独的GPU线程

Renderer Process:

Compositor Thread:

1,操作系统告诉浏览器开启一个帧
2,这个线程首先会接受人任何的输入事件,并尝试直接与Gpu沟通处理,如果输入事件无法处理,则会将任务转交给main thread处理,这个线程也负责在帧结束后,将数据commit给gpu处理

Main Thread:

js脚本执行,解析html,计算样式,组合图层等大多数工作都在这个线程中执行,因为执行的任务比较多,所以这个线程最容易造成浏览器出现卡顿。

Compositor Tile Worker(s):

负责初始化main thread

渲染进程中的Main thread

一个帧的主要执行工作顺序如下:

image.png

input event handlers: 处理输入事件

requestAnimationFrame: 这是对屏幕进行可视更新的理想场所,因为您有新的输入数据,并且它与您将获得的vsync事件很接近。

Parse HTML: 解析html文件,创建dom元素。

Recalc Styles: ,计算元素样式

Layout: 计算大小位置几何信息

Update Layer Tree: 创建堆叠上下文和深度排序元素的过程。

Paint: 这是两部分过程中的第一部分:绘画是绘制调用的记录(例如在这里填充一个矩形,在那里写文本),用于任何新建的或者视觉发生变化的元素。<br/> 第二部分是栅格化(见下文),执行绘制调用,填充纹理。
这部分是绘制调用的记录,通常比栅格化快得多,但这两部分通常统称为“painting”。 Composite
计算图层和图块信息并将其传递回Compositor Thread以供其处理。除其他外,这将解决诸如will-change,重叠元素和任何硬件加速画布之类的事情。

Raster Scheduled and Rasterize: Paint任务中记录的绘制调用会在这里执行。
这在 Compositor Tile Workers 中完成,其数量取决于平台和设备功能。
例如,在Android上,您通常会找到一个工作者,在桌面上您有时可以找到四个。 栅格化是根据图层完成的,每个图层都由图块组成。

Frame End: 随着各个图层的图块都被栅格化、任何新图块都将和输入数据(可能已在事件处理程序中被更改)一起被提交给GPU线程。 Frame Ships 最后,但绝不是最不重要的,GPU线程将图块上传到GPU。
GPU,使用四边形和矩阵将图块绘制到屏幕上。

requestIdleCallback: 如果Main Thread在帧结束时有空余时间,那么requestIdleCallback可以触发。
这是进行非必要工作的绝佳机会,例如收集统计数据。
如果您是刚接触requestIdleCallback

注意:javscript执行引擎和页面渲染引擎在同一个渲染进程,GUI渲染引擎和js执行引擎是互斥的

结尾:fiber使用requestIdleCallback函数使任务在每一帧的空闲时间执行,执行不完,会等到下一帧的空闲时间继续执行 为什么要在空闲时间执行呢,因为一帧内,任务的执行是由顺序的,通常这些任务会执行很快,但是js任务繁重的情况下,会影响到后续样式渲染的,因此,只有把js任务放在帧的空闲时间内执行,浏览器才能保证一秒有60帧所有的渲染次数,用户才不会感受到页面卡顿的情况