DOM 性能大幅提升 - WebKit 的 innerHTML 速度加快了 240%

我们很高兴地看到,一些常见的 DOM 操作的速度大幅提升。这些更改是在 WebKit 级别进行的,可提升 Safari (JavaScriptCore) 和 Chrome (V8) 的性能。

Chrome 工程师 Kentaro Hara 对 WebKit 进行了七项代码优化;以下是优化结果,展示了 JavaScript DOM 访问速度提升了多少:

DOM 性能提升摘要

下面,Kentaro Hara 详细介绍了他修复的一些补丁。这些链接指向的是包含测试用例的 WebKit 错误,以便您亲自尝试这些测试。这些更改是在 WebKit r109829 和 r111133 之间进行的:Chrome 17 不包含这些更改;Chrome 19 包含这些更改。

div.innerHTMLdiv.outerHTML 的性能提高了 2.4 倍 (V8、JavaScriptCore)

WebKit 中的旧行为:

  • 为每个代码创建一个字符串。
  • 将创建的字符串附加到 Vector<string>,解析 DOM 树。
  • 解析后,分配一个大小为 Vector<string> 中所有字符串总和的字符串。
  • 连接 Vector<string> 中的所有字符串,并将其作为 innerHTML 返回。

WebKit 中的新行为: 1. 分配一个字符串,例如 S。1. 将每个标记的字符串串联到 S,以增量方式解析 DOM 树。1. 将 S 返回为 innerHTML

简而言之,补丁会创建一个字符串,然后仅以增量方式附加字符串,而不是创建许多字符串并将它们串联起来。

将 Chromium/Mac 中的 div.innerTextdiv.outerText 的性能提高了 4 倍 (V8/Mac)

该补丁只是更改了创建 innerText 的初始缓冲区大小。将初始缓冲区大小从 2^16 更改为 2^15 后,Chromium/Mac 性能提高了 4 倍。此差异取决于底层 malloc 系统。

将 JavaScriptCore 中 CSS 属性访问的性能提高了 35%

CSS 属性字符串(例如 .fontWeight.backgroundColor)会在 WebKit 中转换为整数 ID。此转换会占用大量资源。该补丁会将转化结果缓存在映射中(即媒体资源字符串 => 整数 ID),以免重复进行转化。

测试的运作方式

它们用于衡量媒体资源访问的时间。对于 innerHTMLbugs.webkit.org/show_bug.cgi?id=81214 中的性能测试),测试仅测量运行以下代码所需的时间:

for (var i = 0; i < 1000000; i++)
    document.body.innerHTML;

性能测试使用从 HTML 规范中复制的大量正文。

同样,CSS 属性访问测试会衡量以下代码的运行时间:

var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
    spanStyle.invalidFontWeight;
    spanStyle.invalidColor;
    spanStyle.invalidBackgroundColor;
    spanStyle.invalidDisplay;
}

好消息是,Hara Kentaro 认为,其他重要的 DOM 属性和方法也有望实现更出色的性能提升。

来吧!

感谢 Haraken 和团队的其他成员。