我們很高興看到某些常見的 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 的新行為:分配一個字串,例如 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%
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;
}
好消息是,Kentaro Hara 認為其他重要的 DOM 屬性和方法,也有機會進一步改善效能。
來吧!
感謝 Haraken 和其他團隊成員。