我们很高兴地看到,一些常见的 DOM 操作的速度大幅提升。这些更改是在 WebKit 级别进行的,可提升 Safari (JavaScriptCore) 和 Chrome (V8) 的性能。
Chrome 工程师 Kentaro Hara 对 WebKit 进行了七项代码优化;以下是优化结果,展示了 JavaScript DOM 访问速度提升了多少:
DOM 性能提升摘要
div.innerHTML
和div.outerHTML
性能提升了 2.4 倍 (V8、JavaScriptCore)- Chromium/Mac 中的
div.innerText
和div.outerText
性能提升了 4 倍 (V8/Mac) - CSS 属性访问速度提升了 35% (JavaScriptCore)
div.classList
、div.dataset
和div.attributes
性能提升幅度最高可达 10.9 倍 (V8)div.firstElementChild
、lastElementChild
、previousElementSibling
和nextElementSibling
性能提升了 7.1 倍 (V8)- V8 DOM 属性访问速度提高了 4 到 5% (V8)
下面,Kentaro Hara 详细介绍了他修复的一些补丁。这些链接指向的是包含测试用例的 WebKit 错误,以便您亲自尝试这些测试。这些更改是在 WebKit r109829 和 r111133 之间进行的:Chrome 17 不包含这些更改;Chrome 19 包含这些更改。
将 div.innerHTML
和 div.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.innerText
和 div.outerText
的性能提高了 4 倍 (V8/Mac)
该补丁只是更改了创建 innerText
的初始缓冲区大小。将初始缓冲区大小从 2^16 更改为 2^15 后,Chromium/Mac 性能提高了 4 倍。此差异取决于底层 malloc 系统。
将 JavaScriptCore 中 CSS 属性访问的性能提高了 35%
CSS 属性字符串(例如 .fontWeight
、.backgroundColor
)会在 WebKit 中转换为整数 ID。此转换会占用大量资源。该补丁会将转化结果缓存在映射中(即媒体资源字符串 => 整数 ID),以免重复进行转化。
测试的运作方式
它们用于衡量媒体资源访问的时间。对于 innerHTML
(bugs.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 和团队的其他成员。