这是来自 Timothy Nikkel 博客 的转载。
延迟框架构建是 Gecko 中的新特性,它允许许多 DOM 操作(appendChild、insertBefore 等)不立即触发重排。这可以极大地提高非常复杂的网页的交互性能。如果您想测试它,您应该获取一个 Firefox Nightly 版本。
延迟框架构建最近已合并到 mozilla-central。为了解释这意味着什么以及它如何改进问题,我们需要一些背景知识。网页 DOM 树中的每个节点都有一个为其创建的框架,用于确定节点在页面上的绘制位置及其大小。框架与 CSS 规范中的盒子概念 紧密相关。我们过去会急切地为 DOM 节点创建框架;也就是说,一旦节点插入到文档中,我们就会为其创建框架。但在许多情况下,这可能会造成不必要的开销。例如,如果脚本将大量节点插入到 DOM 中,我们会在插入每个节点时为其创建一个框架。但是,使用延迟框架构建,我们可以一次性批量处理所有这些节点,从而节省开销。此外,创建这些框架所需的时间不再阻塞该脚本,因此脚本可以继续执行其需要执行的操作,并在需要时创建框架。在其他情况下,脚本会将节点插入文档并立即删除它们,因此无需为这些节点创建框架,因为它们永远不会绘制在屏幕上。
因此,现在当节点插入文档时,节点会被标记为需要为其创建框架,然后在下一次刷新驱动程序发出通知时(当前为 20 毫秒间隔),框架就会被创建。刷新驱动程序也是驱动网页重排和 CSS 及 SVG 动画的程序。
让我们看看延迟框架构建有助于的两个示例。
在这个示例中,我们插入 80000 个 div 元素,然后刷新所有挂起的布局以计算脚本完成更改并对用户可见所需的时间。脚本可以继续执行而无需刷新布局,但我们在这里这样做是为了衡量实际工作所需的时间。
var stime = new Date();
var container = document.getElementById("container");
var lastchild = document.getElementById("lastchild");
for (var i = 0; i < 80000; i++) {
var div = document.createElement("div");
container.insertBefore(div, lastchild);
}
document.documentElement.offsetLeft; // flush layout
var now = new Date();
var millisecondselapsed = (now.getTime() - stime.getTime());
使用延迟框架构建,我们能够通过一个操作处理所有 80000 个 div 元素的插入,从而节省了 80000 次不同插入的开销。在没有延迟框架构建的版本中,我得到的平均时间为 1358 毫秒,使用延迟框架构建,我得到 777 毫秒。
此示例来自一个真实的网页。我们追加一个 div,然后设置“div.style.position = 'absolute';”,并重复 2000 次,然后刷新所有挂起的布局以计算脚本完成更改并对用户可见所需的时间。
var stime = new Date();
var container = document.getElementById("container2");
for (var i = 0; i < 2000; i++) {
var div = document.createElement("div");
container.appendChild(div);
div.style.position = "absolute";
}
document.documentElement.offsetLeft; // flush layout
var now = new Date();
var millisecondselapsed = (now.getTime() - stime.getTime());
使用延迟框架构建,我们甚至在将位置设置为绝对之前都不会费心为 div 创建框架,因此我们不会浪费任何精力。在没有延迟框架构建的版本中,我得到的平均时间为 4730 毫秒,使用延迟框架构建,我得到 130 毫秒。
关于 Paul Rouget
Paul 是一位 Firefox 开发人员。
40 条评论