Tăng hiệu quả nén với từ điển dùng chung

Ngày xuất bản: 6 tháng 3 năm 2024

Nén dữ liệu là một kỹ thuật tối ưu hoá hiệu suất đã được kiểm chứng theo thời gian, giúp giảm kích thước của các tài nguyên trang đủ điều kiện. Trong một thời gian, việc chủ yếu sử dụng gzip trên các máy chủ web để nén các tài nguyên trang dựa trên văn bản thông thường như tệp HTML, CSS và JavaScript, rồi gửi chúng đến máy khách nơi chúng có thể được giải nén là một phương pháp phổ biến. Kết quả là thời gian tải tài nguyên nhanh hơn mà không ảnh hưởng đến hành vi dự kiến của một trang.

Mặc dù gzip tự nó đã rất hiệu quả, nhưng những năm gần đây, chúng ta đã nhận thấy những điểm cải thiện hơn nữa về khả năng nén trên web. Năm 2016, thuật toán Brotli được phát hành trong Chrome, mang lại tỷ lệ nén tổng thể tốt hơn cho các tài nguyên đủ điều kiện. Đến cuối năm 2017, tất cả các trình duyệt hiện đại đều hỗ trợ Brotli và khả năng hỗ trợ Brotli của máy chủ bắt đầu trở nên phổ biến hơn. Gần đây hơn, Chrome đã phát hành tính năng nén ZStandard.

Tuy nhiên, công việc không chỉ dừng lại ở đó! Nhóm Chrome đã nỗ lực để tạo ra các từ điển dùng chung có thể sử dụng trên web. Các từ điển này hiện có trong bản dùng thử theo nguyên gốc cho cả Brotli và ZStandard. Từ điển dùng chung có thể bổ sung cho tính năng nén Brotli và ZStandard để mang lại tỷ lệ nén cao hơn đáng kể cho những trang web thường xuyên gửi mã đã cập nhật và trong một số trường hợp, có thể mang lại tỷ lệ nén từ 90% trở lên. Bài đăng này trình bày chi tiết hơn về cách hoạt động của từ điển dùng chung và cách bạn có thể đăng ký dùng thử nguồn gốc để sử dụng từ điển này cho Brotli và ZStandard trên trang web của mình. Bạn cũng có thể tham khảo video này:

Giải thích về từ điển dùng chung

Nén là một quy trình tìm các chuỗi dư thừa trong dữ liệu đầu vào và sử dụng thông tin đó để tạo ra một đầu ra nhỏ hơn nhiều, có thể đảo ngược sau này. Việc nén hoạt động hiệu quả trên web vì giúp giảm đáng kể thời gian tải tài nguyên. Cả Brotli và ZStandard đều có thể tăng hiệu quả hơn nữa bằng cách sử dụng từ điển nén. Đây là một tập hợp các mẫu bổ sung mà các thuật toán này có thể sử dụng trong quá trình nén. Trên thực tế, Brotli đạt được hiệu quả cao ở một mức độ nào đó bằng cách sử dụng một từ điển nội bộ.

Tuy nhiên, bạn có thể sử dụng từ điển do người dùng tuỳ chỉnh với Brotli và ZStandard có chứa các mẫu dành riêng cho một số tài nguyên. Trên thực tế, từ điển tuỳ chỉnh là một tệp bên ngoài có thể áp dụng cho mọi dữ liệu đầu vào. Từ điển có thể rất cụ thể đối với mã sản xuất của một ứng dụng hoặc thực sự là bất kỳ nội dung nào. Mức độ phù hợp của một từ điển nhất định với dữ liệu đầu vào có thể ảnh hưởng lớn đến hiệu quả nén tổng thể. Những từ điển có nội dung tương tự như nội dung đầu vào sẽ tạo ra đầu ra có tỷ lệ nén cao hơn so với những từ điển có nội dung chung chung hoặc không tương tự.

Sau đây là ví dụ về mức độ hiệu quả của từ điển nén tuỳ chỉnh: giả sử trang web của bạn sử dụng khung Angular và phiên bản hiện tại mà bạn đang dùng là phiên bản 1.7.9. Phiên bản này của khung Angular có kích thước khoảng 172 KiB khi chưa nén. Khi được nén bằng chế độ cài đặt mặc định của Brotli, kích thước của tệp này sẽ là khoảng 53 KiB. Điều này mang lại tỷ lệ nén gần 70%. Tuy nhiên, giả sử sau này bạn quyết định nâng cấp lên Angular 1.8.3. Vì phiên bản Angular này có kích thước gần bằng phiên bản 1.7.9, nên bạn có thể kỳ vọng tỷ lệ nén gần như giống với phiên bản trước.

Đây là nơi từ điển tuỳ chỉnh có thể phát huy tác dụng bằng cách sử dụng một quy trình được gọi là nén delta. Đây là khi từ điển của phiên bản trước của một tài nguyên có thể được dùng để nén một phiên bản sau. Sử dụng ví dụ trước, nếu bạn nén Angular phiên bản 1.8.3 bằng phiên bản 1.7.9 làm từ điển, thì đầu ra sẽ chỉ hơn 4 KiB. Điều này thể hiện tỷ lệ nén gần 98%. Rõ ràng, từ điển nén có thể ảnh hưởng lớn đến hiệu suất tải và hiệu quả của từ điển nén đã được nhận thấy trong các ứng dụng thực tế!

Tuy nhiên, có một thách thức trong việc triển khai quy trình này trên web. Vấn đề là nếu sử dụng một từ điển để nén một tài nguyên, bạn cần có cùng từ điển đó để giải nén tài nguyên. Quy trình này đã từng được thử nghiệm trên web (cụ thể là SDCH) nhưng khó triển khai một cách an toàn. Đề xuất mới nhất này về tính năng nén từ điển dùng chung giải quyết những lo ngại đó, đồng thời mang lại lợi ích đáng kể cho cả tài nguyên tĩnh và tài nguyên động.

Cách Chrome thông báo về việc hỗ trợ từ điển dùng chung

Tất cả trình duyệt đều quảng cáo các thuật toán nén mà chúng hỗ trợ thông qua tiêu đề của yêu cầu Accept-Encoding. Nội dung của tiêu đề là danh sách các định dạng mã hoá được hỗ trợ, phân tách bằng dấu phẩy:

Accept-Encoding: gzip, br, zstd

Tiêu đề Accept-Encoding cụ thể này cho biết rằng trình duyệt yêu cầu tài nguyên hỗ trợ các thuật toán nén gzip, Brotli và ZStandard. Sau đó, máy chủ web phản hồi yêu cầu có thể quyết định sử dụng thuật toán nào khi phản hồi yêu cầu.

Khi tính năng hỗ trợ từ điển dùng chung được bật và có một từ điển liên quan cho một tài nguyên, các mã thông báo bổ sung sẽ được thêm vào tiêu đề Accept-Encoding. Các mã thông báo này là br-d cho Brotli và zstd-d cho Zstandard. Chrome cũng sẽ bao gồm hàm băm của một từ điển có sẵn (sẽ được đề cập ở phần tiếp theo).

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

Nếu được định cấu hình để nhận dạng mã thông báo này và nhận dạng từ điển, thì máy chủ web có thể phản hồi yêu cầu đó bằng một tài nguyên được nén bằng từ điển cho phương thức mã hoá có thể áp dụng. Cách đạt được điều này trên thực tế phụ thuộc vào việc yêu cầu là dành cho tài nguyên tĩnh hay tài nguyên động.

Nén từ điển dùng chung cho tài nguyên tĩnh

Tài nguyên trang tĩnh là tài nguyên luôn tạo ra cùng một phản hồi cho một URL được yêu cầu. Các ví dụ phổ biến về tài nguyên trang tĩnh có thể nén là tệp JavaScript và CSS. Các tài nguyên này thường được phân phiên bản cho mục đích lưu vào bộ nhớ đệm theo một cách nào đó – đôi khi bằng hàm băm nội dung của tệp trong tên tệp (ví dụ: styles.abcd1234.css) hoặc một phương thức khác để tạo dấu vân tay cho tài nguyên. Các loại tài nguyên này là lựa chọn phù hợp cho phương thức nén delta mà các từ điển dùng chung cung cấp, vì tài nguyên tĩnh thường được lưu vào bộ nhớ đệm trong thời gian dài và có xu hướng được cập nhật thường xuyên.

Bạn có thể chỉ định một từ điển cho tài nguyên tĩnh bằng cách đặt tiêu đề phản hồi Use-As-Dictionary cho tài nguyên đó. Tiêu đề này lấy một trong số ít cặp khoá/giá trị, nhưng cặp khoá/giá trị duy nhất bắt buộc là match. Cặp này chấp nhận cú pháp URLPattern chỉ định đường dẫn tài nguyên nơi từ điển sẽ được dùng:

Use-As-Dictionary: match="/dist/styles.*.css"

Hãy coi tiêu đề Use-As-Dictionary là một cơ chế áp dụng cho các phiên bản tài nguyên trong tương lai khớp với mẫu được chỉ định trong tiêu đề đó. Giả sử trang web của bạn gửi tất cả các kiểu trong một tệp CSS duy nhất. Để đơn giản, giả sử phiên bản đầu tiên của tài nguyên đó nằm tại /dist/styles.v1.css và được gửi bằng tiêu đề phản hồi Use-As-Dictionary chứa giá trị match/dist/styles.*.css.

Sau một thời gian, bạn cập nhật CSS của trang web và phát hành một phiên bản mới tại /dist/styles.v2.css. Vì giá trị match được dùng trong tiêu đề phản hồi Use-As-Dictionary của phiên bản trước áp dụng cho yêu cầu này, nên trình duyệt sẽ gửi tiêu đề Available-Dictionary chứa hàm băm của từ điển được mã hoá dưới dạng trình tự byte của trường có cấu trúc:

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

Tại thời điểm này, máy chủ sẽ định cấu hình tính năng nén ở phía máy chủ để đảm bảo sử dụng từ điển so khớp. Sau đó, tài nguyên được nén bằng từ điển đó sẽ được gửi và từ điển có sẵn trong bộ nhớ đệm của trình duyệt người dùng sẽ được dùng để giải nén tài nguyên.

Nếu bạn thường xuyên vận chuyển mã mới cho trang web của mình, thì tính năng nén delta có thể giúp ích rất nhiều. Tuy nhiên, quy trình này khá linh hoạt. Nếu trình duyệt không xác định được rằng có từ điển trong bộ nhớ đệm của trình duyệt người dùng, thì trình duyệt sẽ không chỉ định các mã thông báo br-d hoặc zstd-d bổ sung trong tiêu đề Accept-Encoding. Trong trường hợp đó, quy trình nén tiêu chuẩn sẽ được áp dụng.

Nén từ điển dùng chung cho tài nguyên động

Tài nguyên động cũng có thể hưởng lợi từ tính năng nén từ điển dùng chung. Tài nguyên động là những tài nguyên thay đổi dựa trên một bối cảnh, chẳng hạn như một trang web tin tức nơi trang chính được cập nhật thường xuyên khi có tin tức mới. Tài liệu HTML thường là tài nguyên động. Trong những trường hợp như vậy, từ điển có thể chứa hầu hết cấu trúc HTML và mã mẫu phổ biến của trang web, dẫn đến các trang được nén, trong đó chỉ những phần riêng biệt của mỗi trang được gửi đi.

Do tính chất của các tài nguyên được tạo động, một từ điển phải được tải trên máy khách để sử dụng sau này. Việc tải từ điển trước có nghĩa là việc áp dụng phương pháp nén từ điển dùng chung cho các tài nguyên động chỉ mang tính suy đoán. Trong những trường hợp như vậy, bạn hy vọng rằng trang web của mình sẽ nhận được đủ lưu lượng truy cập để có thể phân bổ chi phí từ điển cho một số lượng lớn lượt điều hướng. Nếu bạn quyết định dùng tính năng này, bước đầu tiên là chỉ định vị trí của từ điển bằng phần tử <link> trong HTML của trang:

<link rel="dictionary" href="/dictionary.dat">

Khi gặp phải phần tử <link> này, Chrome có thể tìm nạp từ điển khi trang ở trạng thái rảnh và ở mức độ ưu tiên thấp để tránh tranh chấp băng thông. Phản hồi cho chính từ điển phải chỉ định một tiêu đề Use-As-Dictionary và chỉ định đường dẫn tài nguyên động mà từ điển áp dụng:

Use-As-Dictionary: match="/product/*"

Từ đây, quy trình này phần lớn giống như đối với tài nguyên tĩnh. Trình duyệt sẽ thấy rằng từ điển đó áp dụng cho các tài nguyên phù hợp và trình duyệt sẽ đính kèm tiêu đề Available-Dictionary vào yêu cầu kèm theo một hàm băm nội dung của từ điển. Tương tự như quy trình tài nguyên tĩnh đã giải thích trước đó.

Nén tài nguyên tĩnh tại thời gian xây dựng

Nếu đã quen thuộc với các trình đóng gói, thì có thể bạn đã biết đến nhiều trình bổ trợ cho các trình đóng gói này. Các trình bổ trợ này có thể nén tài nguyên tại thời gian xây dựng và sau đó phân phát những tài nguyên đã nén đó. Ví dụ: Apache cho phép bạn sử dụng các chỉ thị để phân phát những tài nguyên được nén trước đó tại thời điểm yêu cầu.

Hầu hết các trình đóng gói dựa trên Node.js đều hỗ trợ nén bằng thư viện Zlib tích hợp của Node. Zlib hỗ trợ Brotli và các trình đóng gói sử dụng Brotli thường cung cấp một giao diện để truyền các lựa chọn trực tiếp vào Zlib, hỗ trợ tính năng nén có hỗ trợ từ điển. Sau đây là một số trình đóng gói hỗ trợ việc sử dụng từ điển:

Xin lưu ý rằng các từ điển có sẵn cho một phiên bản tài nguyên bất kỳ có thể sử dụng một trong các phiên bản tài nguyên trước đó. Điều này có nghĩa là bạn sẽ cần phân tích lưu lượng truy cập của người dùng và lập kế hoạch cho phù hợp. Hãy cố gắng cân bằng và tạo ra những tài nguyên mang lại lợi ích cho nhiều người dùng quay lại nhất có thể. Các nhà cung cấp CDN hiện đang thử nghiệm tính năng nén từ điển dùng chung. Hiện chưa có quy trình triển khai nào được cung cấp cho người dùng công khai, nhưng chúng tôi hy vọng điều này sẽ thay đổi!

Hãy dùng thử ngay!

Việc tích hợp tính năng nén từ điển dùng chung với các chức năng nén hiện có của trình duyệt có khả năng cải thiện đáng kể hiệu suất tải cho những trang web thường xuyên gửi mã sản xuất đã cập nhật và nhận được lưu lượng truy cập đáng kể từ khách truy cập cũ. Nếu muốn thử nén từ điển dùng chung, bạn có 2 lựa chọn:

  1. Nếu chỉ muốn tự mình thử nghiệm tính năng nén từ điển dùng chung để hiểu cách hoạt động của tính năng này, bạn có thể bật tính năng thử nghiệm Truyền tải từ điển nén trên trang chrome://flags.
  2. Nếu bạn muốn dùng thử tính năng này trên trang web phát hành công khai và xem tính năng nén từ điển dùng chung có thể mang lại lợi ích gì cho người dùng thực, hãy đăng ký dùng thử nguồn gốc để nhận mã thông báo và tìm hiểu cách hoạt động của các bản dùng thử nguồn gốc.

Kết luận

Chúng tôi rất hào hứng với bước tiến lớn này trong công nghệ nén trên web, cũng như tốc độ nhanh hơn mà công nghệ này có thể mang lại cho các ứng dụng hiện có mà mọi người sử dụng hằng ngày. Bạn nên dùng thử tính năng này và quan trọng nhất là chúng tôi muốn lắng nghe ý kiến của bạn nếu bạn dùng thử! Nếu bạn phát hiện thấy lỗi, hãy báo cáo lỗi tại crbug.com. Để biết thêm tài nguyên và công cụ, hãy truy cập use-as-dictionary.com. Cuối cùng, nếu bạn muốn tìm hiểu sâu hơn về cách hoạt động của tính năng này, thì bài giải thích là bước tiếp theo phù hợp!