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

Nén dữ liệu là một kỹ thuật tối ưu hoá hiệu suất đã được kiểm chứng qua 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, phương pháp phổ biến là chủ yếu sử dụng gzip trên máy chủ web để nén các tài nguyên trang dựa trên văn bản phổ biến như tệp HTML, CSS và JavaScript, đồng thời gửi các tài nguyên đó đến máy khách để có thể giải né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 trang.

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

Tuy nhiên, công việc vẫn chưa dừng lại ở đó! Nhóm Chrome đã nỗ lực để giúp bạn có thể sử dụng từ điển dùng chung trên web. Hiện tại, bạn có thể dùng từ điển dùng chung trong một thử nghiệm gốc cho cả Brotli và ZStandard. Từ điển dùng chung có thể bổ sung 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à có thể – trong một số trường hợp – 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ử phiên bản gốc để sử dụng từ điển này cho Brotli và ZStandard trên trang web của mình.

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

Nén là quá trình tìm các trình tự dư thừa trong dữ liệu đầu vào và sử dụng thông tin đó để tạo ra một dữ liệu đầu ra nhỏ hơn nhiều. Dữ liệu đầu ra này có thể được đảo ngược sau này. Tính năng 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 suất cao ở một mức độ nào đó bằng cách sử dụng từ điển nội bộ.

Tuy nhiên, bạn có thể sử dụng từ điển tuỳ chỉnh do người dùng tuyển chọn với Brotli và ZStandard chứa các mẫu dành riêng cho các tài nguyên cụ thể. Trong thực tế, từ điển tuỳ chỉnh là một tệp bên ngoài có thể áp dụng cho bất kỳ dữ liệu đầu vào nào. Từ điển có thể rất cụ thể đối với mã phát hành công khai của ứ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ể tác động lớn đến hiệu quả nén tổng thể. Những từ điển rất giống với nội dung của dữ liệu đầu vào sẽ tạo ra kết quả 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 giống nhau.

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 bạn đang sử dụng là phiên bản 1.7.9. Phiên bản khung Angular này 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ẽ trở thành khoảng 53 KiB. Điều này mang lại tỷ lệ nén gần 70%. Tuy nhiên, giả sử bạn quyết định nâng cấp lên Angular 1.8.3 sau này. Do phiên bản Angular này có kích thước gần giống với phiên bản 1.7.9, nên bạn có thể dự kiến tỷ lệ nén gần giống với phiên bản trước.

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

Tuy nhiên, có một thách thức trong việc làm cho quy trình này hoạt động trên web. Điểm mấu chốt là nếu sử dụng từ điển để nén một tài nguyên, bạn cần chính từ điển đó để giải nén tài nguyên đó. Quy trình này đã được thử nghiệm trên web trước đây (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 chung giải quyết những mối lo ngại đó, đồng thời mang lại lợi ích đáng kể cho cả tài nguyên tĩnh và động.

Cách Chrome quảng cáo tính năng 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 đề yêu cầu Accept-Encoding. Nội dung của tiêu đề là danh sách các bộ mã hoá được hỗ trợ, được 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 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 bạn bật tính năng hỗ trợ từ điển dùng chung và có từ điển phù hợp 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, nội dung này sẽ được đề cập trong 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 bộ mã hoá hiện hành. Cách thực hiện việc này trong thực tế phụ thuộc vào việc yêu cầu là cho tài nguyên tĩnh hay độ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 tạo phiên bản cho mục đích lưu vào bộ nhớ đệm theo một cách nào đó – đôi khi có hàm băm của nội dung tệp trong tên tệp (ví dụ: styles.abcd1234.css) hoặc một số phương thức khác để tạo vân tay số cho tài nguyên. Những loại tài nguyên này là ứng cử viên tuyệt vời cho phương thức nén delta mà 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 với một tần suất nhất định.

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 đề lấy một trong số ít cặp khoá/giá trị, nhưng cặp bắt buộc duy nhất là match, chấp nhận ngữ pháp URLPattern chỉ định đường dẫn tài nguyên nơi sử dụng từ điển:

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 sau này của tài nguyên khớp với mẫu được chỉ định trong đó. Giả sử trang web của bạn phân phối tất cả các kiểu trong một tệp CSS. Để đơn giản, giả sử phiên bản đầu tiên của tài nguyên đó nằm ở /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 khoảng thời gian, bạn cập nhật CSS của trang web và phân phối phiên bản mới của CSS đó tại /dist/styles.v2.css. Vì giá trị match 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 một 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 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ủ có thể tuỳ ý định cấu hình tính năng nén để đả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 của người dùng sẽ được dùng để giải nén tài nguyên đó.

Nếu bạn thường xuyên gửi 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 rất linh hoạt. Nếu không xác định được từ điển có trong bộ nhớ đệm của trình duyệt của 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

Các 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 ngữ cảnh, chẳng hạn như trang web tin tức mà 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 chỉ gửi các phần riêng biệt của mỗi trang.

Do bản chất của tài nguyên được tạo động, bạn phải tải từ điển 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 tính năng nén từ điển dùng chung cho các tài nguyên động là suy đoán. Trong những trường hợp như vậy, hy vọng là trang web của bạn nhận được đủ lưu lượng truy cập để có thể phân bổ chi phí từ điển trên một số lượng lớn lượt điều hướng. Nếu bạn quyết định thử, bước đầu tiên là chỉ định vị trí của từ điển thông qua phần tử <link> trong HTML của trang:

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

Khi gặp 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 tiêu đề Use-As-Dictionary và chỉ định đường dẫn tài nguyên động mà phản hồi đó áp dụng:

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

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

Nén tài nguyên tĩnh tại thời điểm tạo bản dựng

Nếu đã quen thuộc với trình tạo gói, bạn có thể quen thuộc với nhiều trình bổ trợ cho trình tạo gói có thể nén tài nguyên tại thời điểm tạo bản dựng và sau đó phân phát các tài nguyên nén đó. Ví dụ: Apache cho phép bạn sử dụng các lệnh để phân phát các 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 tạo gói dựa trên Node.js hỗ trợ tính năng nén đều sử dụng thư viện Zlib tích hợp của Node. Zlib hỗ trợ Brotli và các trình kết hợp sử dụng Brotli thường cung cấp một giao diện để truyền các tuỳ 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 hiện có cho bất kỳ phiên bản tài nguyên nào 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 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 tối đa cho số lượng người dùng quay lại nhiều 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ó cách triển khai nào để sử dụng công khai, nhưng chúng tôi dự kiến đ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 tính năng nén hiện có của trình duyệt có thể cải thiện đáng kể hiệu suất tải cho những trang web thường xuyên gửi mã phát hành chính thức đã 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ử tính năng nén từ điển dùng chung, bạn có hai lựa chọn:

  1. Nếu chỉ muốn tự tìm hiểu cách hoạt động của tính năng nén từ điển dùng chung, 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 thử tính năng này trên trang web chính thức và xem cách tính năng nén từ điển dùng chung có thể mang lại lợi ích cho người dùng thực tế, hãy đăng ký dùng thử phiên bản gốc để nhận mã thông báo và đọc về cách hoạt động của phiên bản gốc.

Kết luận

Chúng tôi rất hào hứng về sự tiến bộ lớn này trong công nghệ nén trên web và mứ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 biết ý kiến của bạn nếu bạn dùng thử! Nếu bạn phát hiện lỗi, hãy gửi lỗi tại crbug.com. Để biết thêm tài nguyên và công cụ, hãy xem 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ất cả, nội dung giải thích là bước tiếp theo phù hợp!