Bên trong một engine CSS siêu nhanh: Quantum CSS

Bạn có thể đã nghe nói về Project Quantum ... đó là một sự rewrite lớn của nội bộ của Firefox để làm cho Firefox trở nên nhanh hơn. Và thành phần chính đầu tiên của nó - một engine CSS mới gọi là Quantum CSS (trước đây gọi là Stylo) - bây giờ đã sẵn sàng để thử nghiệm trong phiên bản Nightly. Bạn có bật nó bằng cách đi đến about:config và thiết lập layout.css.servo.enabled là true. Engine mới này kết hợp các sáng kiến ​​tân tiến từ bốn trình duyệt khác nhau để tạo ra một siêu engine CSS mới.

Nó tận dụng phần cứng hiện đại, thực hiện công việc song song trên tất cả các lõi trong máy tính. Điều này có nghĩa là nó có thể chạy nhanh hơn đến 2 hoặc 4 hoặc thậm chí 18 lần. Thêm vào đó, nó kết hợp tối ưu hóa hiện tại tối tân từ các trình duyệt khác. Vì vậy, ngay cả khi nó không chạy song song, nó vẫn sẽ là một engine CSS nhanh.

Nhưng engine CSS thực hiện công việc cụ thể gì? Đầu tiên chúng ta hãy nhìn vào engine CSS và cách nó phù hợp với phần còn lại của trình duyệt. Sau đó chúng ta có thể xem Quantum CSS làm cho nó nhanh hơn thế nào.

What does the CSS engine do?

engine CSS là một phần của engine rendering của trình duyệt. engine hiển thị sẽ lấy các tệp HTML và CSS của trang web và biến chúng thành các điểm ảnh trên màn hình.

Mỗi trình duyệt có một engine render. Trong Chrome, nó được gọi là Blink. Trong Edge, nó được gọi là EdgeHTML. Trong Safari, nó được gọi là WebKit. Và trong Firefox, nó được gọi là Gecko. Để có được từ các tệp tin đến các điểm ảnh, tất cả các engine render này sẽ làm những việc tương tự như sau:

  1. Phân tích các tệp tin vào đối tượng mà trình duyệt có thể hiểu, bao gồm cả DOM. Tại thời điểm này, DOM biết về cấu trúc của trang. Nó biết về mối quan hệ giữa cha mẹ và con cái giữa các element. Mặc dù nó không biết các element nên trông như thế nào.

  1. Tìm ra rằng các element nên trông như thế nào. Đối với mỗi node của DOM, engine CSS sẽ tìm ra quy tắc CSS nào được áp dụng. Sau đó, nó tìm ra các giá trị cho mỗi thuộc tính CSS cho node DOM đó.

  1. Tìm ra các kích thước cho mỗi node và nơi nó đi đến trên màn hình. Các box được tạo cho mỗi vật thể sẽ hiển thị trên màn hình. Các box không chỉ biểu diễn các node DOM ... bạn cũng sẽ có các hộp cho các sự vật bên trong các node DOM, như các dòng văn bản.

  1. Sơn các hộp khác nhau. Điều này có thể xảy ra trên nhiều layer. Như thế có thể thay đổi một lớp mà không cần phải sơn lại các vật trên các lớp khác.
  2. Thực hiện các lớp sơn khác nhau, áp dụng bất kỳ thuộc tính compositor-only nào như transforms và biến chúng thành một hình ảnh. Điều này về cơ bản là chụp ảnh các lớp xếp chồng lên nhau. Hình ảnh này sau đó sẽ được hiển thị trên màn hình.

Điều này có nghĩa khi bắt đầu tính các style, engine CSS có hai thứ:

  • một cây DOM
  • một danh sách các quy tắc style Nó đi qua mỗi node DOM, từng cái một, và đưa ra các style cho node DOM đó. Là một phần của nó, nó cho node DOM một giá trị cho mỗi và mọi thuộc tính CSS, ngay cả khi stylesheets không khai báo giá trị cho thuộc tính đó. Giống như một ai đó đi qua và điền vào một form. Họ cần phải điền vào một trong các form này cho mỗi node DOM. Và đối với mỗi field trong form, họ cần có câu trả lời.

Để làm điều này, engine CSS cần làm hai việc:

  • tìm ra những quy tắc áp dụng cho node - selector matching
  • điền vào bất kỳ giá trị thiếu nào với các giá trị từ parent hoặc giá trị mặc định - the cascade

Selector matching

Trong bước này, chúng ta sẽ thêm bất kỳ quy tắc nào phù hợp với node DOM vào một danh sách. Bởi vì nhiều quy tắc có thể phù hợp, có thể có nhiều khai báo cho cùng một thuộc tính.

Thêm vào đó, trình duyệt tự bổ sung thêm một số CSS mặc định (gọi là user agent style sheets). Làm thế nào để các engine CSS biết được giá trị để chọn? Đây là nơi quy tắc specificity đi vào. Các engine CSS cơ bản tạo ra một spreadsheet. Sau đó, nó sắp xếp các declaration dựa trên các cột khác nhau.

Quy tắc có độ specificity cao nhất thắng. Vì vậy, dựa trên bảng tính này, engine CSS điền các giá trị mà nó có thể.

Đối với phần còn lại, chúng tôi sẽ sử dụng cascade.

The cascade

Các cascade làm cho CSS dễ dàng hơn để viết và maintain. Bởi vì với cascade, bạn có thể đặt thuộc tính color ở body và biết rằng văn bản trong các element p, span, và li sẽ sử dụng màu đó (trừ khi bạn có ghi đè cụ thể hơn). Để làm điều này, engine CSS nhìn vào các hộp trống trên form của nó. Nếu thuộc tính thừa kế theo mặc định, thì engine CSS đi lên cây để tìm giá trị cho thuộc tính đó từ một trong những tổ tiên của nó. Nếu không có tổ tiên nào có giá trị, hoặc nếu thuộc tính là không kế thừa, nó sẽ nhận được một giá trị mặc định.

Vì vậy bây giờ tất cả các style đã được tính cho node DOM này.

A sidenote: style struct sharing

CSS có hàng trăm property. Nếu engine CSS giữ giá trị cho mỗi property của mỗi node DOM, nó sẽ sớm cạn kiệt bộ nhớ. Thay vào đó, engine thường làm cái gì đó gọi là chia sẻ style struct. Chúng lưu trữ dữ liệu mà thường đi cùng nhau (như thuộc tính font) trong một object khác gọi là style struct. Sau đó, thay vì lưu tất cả các property trong các object tương tự nhau, các object style đã tính toán chỉ có các con trỏ. Đối với mỗi style, có một con trỏ trỏ tới cấu trúc có giá trị đúng cho node DOM này.

Điều này tiết kiệm cả bộ nhớ và thời gian. Các node có các thuộc tính tương tự (như anh chị em) chỉ có thể trỏ đến cùng các cấu trúc cho các thuộc tính mà chúng chia sẻ. Và vì nhiều thuộc tính được kế thừa, tổ tiên có thể chia sẻ một struct với bất kỳ con cháu nào không chỉ định các ghi đè của chúng.

Ở bài viết sau, chúng ta sẽ cùng xem xét các nhà phát triển của firefox đã làm thế nào để quantium css trở nên siêu nhanh.