Chúng tôi rất vui khi thấy một số thao tác DOM phổ biến vừa tăng tốc nhanh chóng. Các thay đổi này diễn ra ở cấp WebKit, giúp cải thiện hiệu suất cho cả Safari (JavaScriptCore) và Chrome (V8).
Kỹ sư Chrome Kentaro Hara đã thực hiện 7 lần tối ưu hoá mã trong WebKit; dưới đây là kết quả cho thấy tốc độ truy cập DOM JavaScript nhanh hơn bao nhiêu:
Tóm tắt về các tính năng tăng hiệu suất DOM
- Hiệu suất của
div.innerHTML
vàdiv.outerHTML
tăng 2,4 lần (V8, JavaScriptCore) div.innerText
và hiệu suấtdiv.outerText
trong Chromium/Mac tăng gấp 4 lần (V8/Mac)- Số lượt truy cập vào thuộc tính CSS đã cải thiện 35% (JavaScriptCore)
div.classList
,div.dataset
vàdiv.attributes
hiệu suất cải thiện lên đến 10,9 lần (V8)div.firstElementChild
,lastElementChild
,previousElementSibling
vànextElementSibling
hiệu suất cải thiện gấp 7,1 lần (V8)- Quyền truy cập vào thuộc tính DOM của V8 đã cải thiện từ 4 đến 5% (V8)
Dưới đây là thông tin chi tiết về một số bản vá mà Kentaro Hara đã tạo. Các đường liên kết này là đến các lỗi WebKit có trường hợp kiểm thử để bạn có thể tự thử nghiệm. Các thay đổi này được thực hiện giữa WebKit r109829 và r111133: Chrome 17 không bao gồm các thay đổi này; Chrome 19 có.
Cải thiện hiệu suất của div.innerHTML
và div.outerHTML
thêm 2,4 lần (V8, JavaScriptCore)
Hành vi trước đây trong WebKit:
- Tạo một chuỗi cho mỗi thẻ.
- Nối một chuỗi đã tạo vào
Vector<string>
, phân tích cú pháp cây DOM. - Sau khi phân tích cú pháp, hãy phân bổ một chuỗi có kích thước bằng tổng của tất cả các chuỗi trong
Vector<string>
. - Dùng toán tử nối để nối tất cả các chuỗi trong
Vector<string>
và trả về dưới dạnginnerHTML
.
Hành vi mới trong WebKit:
1. Phân bổ một chuỗi, giả sử là S.
1. Dùng toán tử nối để nối một chuỗi cho mỗi thẻ với S, phân tích cú pháp dần dần cây DOM.
1. Trả về S dưới dạng innerHTML
.
Tóm lại, thay vì tạo nhiều chuỗi rồi nối các chuỗi đó, bản vá sẽ tạo một chuỗi rồi chỉ cần nối các chuỗi tăng dần.
Cải thiện hiệu suất của div.innerText
và div.outerText
trong Chromium/Mac gấp 4 lần (V8/Mac)
Bản vá này chỉ thay đổi kích thước vùng đệm ban đầu để tạo innerText
. Việc thay đổi kích thước vùng đệm ban đầu từ 2^16 thành 2^15 đã cải thiện hiệu suất của Chromium/Mac gấp 4 lần. Sự khác biệt này phụ thuộc vào hệ thống malloc cơ bản.
Cải thiện hiệu suất truy cập thuộc tính CSS trong JavaScriptCore thêm 35%
Chuỗi thuộc tính CSS (ví dụ: .fontWeight
, .backgroundColor
) được chuyển đổi thành mã nhận dạng số nguyên trong WebKit. Lượt chuyển đổi này có dung lượng lớn. Bản vá lưu kết quả chuyển đổi vào bộ nhớ đệm trong một bản đồ (tức là một chuỗi thuộc tính => mã nhận dạng số nguyên) để quá trình chuyển đổi không được thực hiện nhiều lần.
Các bài kiểm thử hoạt động như thế nào?
Các chỉ số này đo lường thời gian truy cập vào thuộc tính. Trong trường hợp innerHTML
(kiểm thử hiệu suất trong bugs.webkit.org/show_bug.cgi?id=81214), kiểm thử chỉ đo lường thời gian chạy mã sau:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
Bài kiểm thử hiệu suất sử dụng một nội dung lớn được sao chép từ thông số kỹ thuật HTML.
Tương tự, kiểm thử truy cập thuộc tính CSS đo lường thời gian của mã sau:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
Tin vui là Kentaro Hara tin rằng hiệu suất của các thuộc tính và phương thức DOM quan trọng khác cũng có thể được cải thiện hơn nữa.
Tới luôn!
Xin cảm ơn Haraken và các thành viên khác trong nhóm.