Skip to content

浏览器 frame

一帧内都做了啥 frame

渲染流程 A Picture Speaks A Thousand Words

Renderer Process Threads

渲染进程中的线程

1. Compositor Thread

合成器线程

  1. 是都一个被告知 vsync 时间的线程(操作系统告诉浏览器创建新帧的方式),开启一个新的帧周期
  2. 同时还接受用户事件
  3. 如果可以的话,Compositor Thread 将避免进入 Main Thread,并尝试将输入(例如 滚动)转换为屏幕上的移动,
  4. 将通过更新 layer 位置,并通过 GPU 线程直接将帧交给 GPU 处理
  5. 如果由于输入事件处理程序或其他可视化工作而无法执行上面的操作,则将工作交给 Main Thread

2. Main Thread

主线程

  1. 执行 JavaScript, styles, layout and paint
  2. 执行太多因为会出现卡顿

3.Compositor Tile Worker(s)

由 Compositor Thread 生成的一个或多个工作程序,用于处理栅格化任务

  1. 在许多方面,您应该将 Compositor Thread 视为大 boss
  2. 虽然它不运行 JavaScript,Layout,Paint 或其中任何一个,但它是完全负责初始化 Main Thread 工作,然后将帧传送到屏幕。
  3. 如果它不必等待输入事件处理程序,它可以在等待 Main Thread 完成其工作时,直接发送帧。
  4. Service Workers 和 Web Workers 存活在这个进程中。

主线程

Main Thread

浏览器无需执行上面所有的步骤,例如没有新的 HTML,就不会触发 Parse HTML 提高性能方式通过就是减少部分流程 Recalc Styles 和 Layout 下的红色箭头,它们似乎是指向了 requestAnimationFrame.称为强制同步布局(样式),不利于性能

1.Frame Start

vsync 时间触发后,一个帧周期开始

2.input envnt handlers

输入数据从 Compositor Thread 传递到 Main Thread 上的任何输入事件处理程序 所有输入事件处理程序(touchmove,scroll,click)应首先触发,每帧一次,但不一定是这样, 调度程序会尽力尝试,其成功因操作系统而异。

3. requestAnimationFrame

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

window.requestAnimationFrame(callback);

使用 requestAnimationFrame 实现一个进度条?

4. Parse HTML

任何新添加的 HTML 都需要被处理,并创建 DOM 元素。 在页面加载期间或者之后诸如 appendChild 等操作

5. Recalc Styles

任何新添加或修改的内容都需要重新计算样式。 这可能是整棵树,或者它可以缩小范围,具体取决于更改的内容。

6.Layout

为每个可见元素计算几何信息(每个元素的位置和大小)。 它通常用于整个文档,通常使计算成本与 DOM 大小成比例。

7.Update Layer Tree

创建 Layer Tree 和 生成 绘制顺序表。

8. Paint

这是两部分过程中的第一部分:绘画是绘制调用的记录(例如在这里填充一个矩形,在那里写文本),用于任何新建的或者视觉发生变化的元素。 第二部分是栅格化(见下文),执行绘制调用,填充纹理。 这部分是绘制调用的记录,通常比栅格化快得多,但这两部分通常统称为“painting”。

9.Composite

计算图层和图块信息并将其传递回 Compositor Thread 以供其处理。 除其他外,这将解决诸如 will-change,重叠元素和任何硬件加速画布之类的事情

10. Raster Scheduled and Rasterize

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

11.Frame End

随着各个图层的图块都被栅格化、任何新图块都将和输入数据(可能已在事件处理程序中被更改)一起被提交给 GPU 线程。

12.Frame Ships

最后,但绝不是最不重要的,GPU 线程将图块上传到 GPU。 GPU,使用四边形和矩阵将图块绘制到屏幕上

13.requestIdleCallback

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

js
window.requestIdleCallback =
  window.requestIdleCallback ||
  function (cb) {
    var start = Date.now()
    return setTimeout(function () {
      cb({
        didTimeout: false,
        timeRemaining: function () {
          return Math.max(0, 50 - (Date.now() - start))
        },
      })
    }, 1)
  }

window.cancelIdleCallback =
  window.cancelIdleCallback ||
  function (id) {
    clearTimeout(id)
  }