Devtools 中的 Timeline Paint Profiler 提示正在绘制所有内容

Timeline Paint Profiler in Devtools suggests everything is being painted

当我们在 Chrome 中使用 Paint Profiler 时,我们可以看到正在绘制的内容。我创建了一个简单的示例,每 3 秒向页面添加一个新的 div,这里显示的是正在绘制的内容:

但是当我在时间轴中使用绘图分析器时,看起来一切都在重新绘制:

如屏幕截图所示,在第五次绘制时,我们调用了 5 次 drawTextBlob 调用。这表明所有 5 divs 都被绘制了。我只期待一个。

有人可以解释一下吗?

"Paint" 事件的确切含义随时间发生了变化。过去是在 Paint 期间渲染器直接更新图层的位图,这通常很慢。在那些日子里,您可能会发现绘制的矩形与您实际无效的区域匹配(即在您的情况下只是最后一行),正如您可能期望的那样。

Chrome 渲染子系统的当前实现在其他线程上执行光栅化(试图让事情远离主线程,主线程已经足够忙于 JavaScript 执行,DOM 布局和许多其他东西)或在 GPU 上(如果您想知道平台上的当前模式是什么,请查看 chrome://gpu 中的 "Rasterization" 和 "Multiple raster threads") .因此,您在主线程上看到的 "Paint" 事件只是记录了绘制命令的日志(即您在 Paint Profiler 的左窗格中看到的内容),而没有实际产生任何像素——这是相对较快的,并且 Chrome 选择重新记录整个图层,以便稍后可以选择要光栅化的部分(例如,在预期的滚动情况下)而无需再次进入主线程,这可能会被 运行 JavaScript 或做布局。

现在,如果您将时间轴切换到火焰图模式(工具栏中 "View" 标签附近的右侧图标),您将看到 "Rasterize Paint" 事件,这是实际的光栅化 -- Chrome 选秀在主线程上的 Paint 事件期间记录的 paint 命令日志,并重新播放它为层的片段生成实际像素。当您 select "Rasterize Paint" 时,您可以看到图层的哪一部分被栅格化以及该部分的 Paint Profiler。请注意,不同片段有许多小的 Rasterize Paint 事件,可能在不同的线程上,但它们仍然具有整个日志(即示例中的 5 个 drawTextBlob 命令)。但是,那些不影响正在栅格化的片段的绘制命令将被剔除,因为它们落在片段的剪辑矩形之外,因此不会对栅格化时间产生明显影响。

然后,您可能会注意到被栅格化的片段仍然比您实际无效化的区域大。这是因为 Chrome 根据图块、小矩形位图(通常为 128 x 128,但可能因平台而异)来管理栅格化图层,因此对于大图层(例如比视口长得多的页面),只有可见的部分视口中的内容可以存储在 GPU(通常内存有限)上,并且可以快速上传因滚动而突然变得可见的部分。

最后,由于您在呈现选项中勾选 "Show Paint rectangles",您看到的以绿色突出显示的部分在技术上是一个 "invalidation" 矩形 - 即您的页面区域具有确实 由于 layout/styles 等的变化而发生了变化。这些区域是您作为作者真正可以直接影响的,但如您所见,Chrome 可能会绘画并光栅化更多,主要是出于有效管理大页面滚动的考虑。