我们非常高兴地看到,一些常见的 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
性能 by 4x (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. 以 innerHTML
的形式返回 S。
简而言之,补丁会创建一个字符串,然后以增量方式简单地附加字符串,而不是创建大量字符串并将其串联起来。
将 Chromium/Mac 中的 div.innerText
和 div.outerText
的性能提升了 4 倍 (V8/Mac)
该补丁刚刚更改了用于创建 innerText
的初始缓冲区空间。将初始缓冲区空间从 2^16 更改为 2^15,将 Chromium/Mac 的性能提升了 4 倍。这种差异取决于底层 malloc 系统。
将 JavaScriptCore 中的 CSS 属性访问性能提升了 35%
在 WebKit 中,CSS 属性字符串(例如 .fontWeight
、.backgroundColor
)会转换为整数 ID。这种转化非常耗费资源。该补丁会将转换结果缓存在映射中(即属性字符串 => 整数 ID),因此不会执行多次转换。
这些测试是如何运作的?
它们会衡量访问媒体资源的时间。如果使用 innerHTML
(bugs.webkit.org/show_bug.cgi?id=81214 中的性能测试),该测试仅测量运行以下代码的时间:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
性能测试使用的是从 HTML 规范中复制的大型正文。
同样,CSS property-accesses 测试会测量以下代码的时间:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
但好消息是,Kentaro Hara 认为其他重要的 DOM 属性和方法将能实现更多性能改进。
来吧!
祝好 Haraken 和团队的其他成员。