Tối ưu browser rendering: Flow

web api web performance flow

60fps là mục tiêu cuối cùng của một web page "mượt"

Độ mượt

Trước khi nói về các khía cạnh ảnh hưởng đến render, chúng ta cần biết về output của việc tối ưu render trước. Thứ sau cùng chúng ta nhận được nếu ứng dụng web được tối ưu tốt đó là "độ mượt".

"Độ mượt" là một khái niệm thiên về cảm nhận của mắt người dùng, tuy nhiên, trong ứng dụng web nói riêng và ứng dụng máy tính nói chung, độ mượt có thể đo đếm được bằng một đơn vị, đó là FPS - frames per second (cái này ô nào chơi game đều biết). Các màn hình trên các thiết bị phổ thông (máy tính, điện thoại,...) hầu hết đều có tần số quét là 60hz, hiểu đại khái là màn hình vẽ lại hình ảnh tối đa 60 lần 1 giây. 60Hz cũng là tần số mà mắt người bắt đầu cảm thấy "mượt".

Quay lại ứng dụng web, nếu có animation hoặc hiệu ứng chuyển động nào đó chạy, hoặc đơn giản người dùng cuộn trang, browser cũng sẽ dựa vào tính toán bên dưới và vẽ lại hình ảnh web page cho người dùng. Con số 60 cũng là số hình ảnh (frames) mà trình duyệt cần vẽ mỗi 1 giây, để đảm bảo trình duyệt và màn hình có thể đồng bộ tần số với nhau.

Vì thế trên lý thuyết, mỗi một khung hình sẽ chỉ có ngân sách là 1 / 60 ~ 16ms (mili giây), và trên thực tế trình duyệt sẽ là 10ms để làm mọi việc. Nếu đoạn code của bạn thực thi lâu hơn 10ms, fps sẽ giảm và ứng dụng của bạn sẽ "giật" hoặc "khựng".

Rendering pipeline - quy trình render

Điều đầu tiên cần nhớ trước khi tìm hiểu về redering trên trình duyệt đó là khái niệm rendering pipeline. Quá trình rendering sẽ đi qua 5 bước:

Trong series này chúng ta sẽ tìm hiểu các bước này, chúng ảnh hưởng đến việc render thế nào, và tối ưu chúng thế nào.

Reflows

Reflow là tên gọi của tập hợp nhiều tiến trình mà trình duyệt tính toán lại kích thướcbố trí lại vị trí của các elements trên web page. Tuyệt vời đúng ko, trình duyệt lo hết! Tuy nhiên nhược điểm của quá trình này là nó chạy đồng bộ, tức là reflow mà chưa chạy xong thì thằng đằng sau cứ chờ đấy đã. Cụ thể nếu có quá nhiều tiến trình reflow và trình duyệt ko xử lý kịp thì FPS sẽ giảm, thậm chí = 0 (cứng đơ luôn) hoặc tồi tệ nhất là crash tab.

Một vài sự kiện trong DOM gây kích hoạt reflow:

  • getComputedStyle() - ngon bổ rẻ thì ko đi với nhau bao giờ, thằng này cũng thế, ngon bổ và rất đắt (trả giá bằng reflow)
  • động chạm đến chiều cao hoặc scrolling trong giới hạn box, ví dụ clientHeight, scrollTop;
  • đụng chạm đến chiều cao hoặc scrolling của window, ví dụ clientHeight, scrollY;

Chi tiết hơn các bạn có thể xem ở đây: https://gist.github.com/paulirish/5d52fb081b3570c81e3a

Vậy làm thế nào để vẫn sử dụng các công cụ kể trên mà không làm ảnh hưởng đến performance?

Batching

Kĩ thuật đầu tiên (cũng đơn giản) có tên batching, hiểu đơn giản là nhóm các câu lệnh đọc ghi DOM vào sát nhau, tránh việc đọc ghi DOM rời rạc, gây nên tình trạng reflow liên tục.

Ví dụ:

// Batching.

var w = element.clientWidth + 50;
var w2 = element.clientWidth + 100;

element.style.width = w + 'px';
element.style.width = w2 + 'px';

// và không batching

var w = element.clientWidth + 50;
element.style.width = w + 'px';
var w2 = element.clientWidth + 50;
element.style.width = w2 + 'px';

Một ví dụ khác về batching, đó là khi chúng ta tạo thêm Element vào DOM, chúng ta cũng nên sử dụng

// Không tốt
for(var i = 0; i < 1000; i++){
    var element = document.createElement('div');
    document.body.appendChild(element);
}

// createDocumentFragment() giúp chúng ta chuẩn bị một DOM node bên trong bộ nhớ máy tính, trước khi inject nó vào DOM tree thực
var fragment = document.createDocumentFragment();
for(var i = 0; i < 1000; i++){
    const element = document.createElement('div');
    fragment.appendChild(element);
}
document.body.appendChild(fragment);

Ngoài ra, còn nhiều những yếu tố khác ảnh hưởng đến DOM performance, hãy cùng tìm hiểu ở phần tiếp theo.

Previous Post Next Post