Tăng mạnh hiệu suất DOM - innerHTML của WebKit nhanh hơn 240%

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

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.innerHTMLdiv.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ạng innerHTML.

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.innerTextdiv.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.