Zwiększ efektywność kompresji dzięki udostępnionym słownikom

Kompresja danych to sprawdzona metoda optymalizacji wydajności, która zmniejsza rozmiar kwalifikujących się zasobów strony. Przez jakiś czas powszechną praktyką było używanie na serwerach WWW głównie algorytmu gzip do kompresowania typowych zasobów strony opartych na tekście, takich jak pliki HTML, CSS i JavaScript, oraz wysyłanie ich do klienta, gdzie można je było odtworzyć. W efekcie zasoby wczytują się szybciej, a nie wpływa to na działanie strony.

Chociaż gzip jest bardzo skuteczny sam w sobie, w ostatnich latach udało się wprowadzić dalsze ulepszenia kompresji w internecie. W 2016 r. w Chrome pojawił się algorytm Brotli, który zapewniał lepsze współczynniki kompresji w przypadku kwalifikujących się zasobów. Pod koniec 2017 roku wszystkie nowoczesne przeglądarki obsługiwały Brotli, a obsługa tego algorytmu na serwerach zaczęła się coraz bardziej rozpowszechniać. Niedawno w Chrome wprowadziliśmy kompresję ZStandard.

Na tym jednak nie koniec. Zespół Chrome pracował nad udostępnionymi słownikami, które można teraz używać w internecie. Są one dostępne w ramach testów wersji próbnej pochodzenia zarówno w przypadku Brotli, jak i Zstandard. Udostępnione słowniki mogą uzupełniać kompresję Brotli i ZStandard, zapewniając znacznie wyższe współczynniki kompresji w przypadku witryn, które często wysyłają zaktualizowany kod. W niektórych przypadkach współczynniki kompresji mogą wynosić 90% lub więcej. W tym poście znajdziesz więcej informacji o tym, jak działają współdzielone słowniki, i o tym, jak zarejestrować się w programie testów wersji próbnych, aby korzystać z nich w swojej witrynie w przypadku Brotli i ZStandard.

Wyjaśnienie współdzielonych słowników

Kompresja to proces znajdowania nadmiarowych sekwencji w danych wejściowych i używania tych informacji do tworzenia znacznie mniejszych danych wyjściowych, które można później odwrócić. Kompresja działa dobrze w internecie, ponieważ znacznie skraca czas wczytywania zasobów. Zarówno Brotli, jak i Zstandard mogą zwiększyć swoją skuteczność, korzystając z słownika kompresji, czyli zbioru dodatkowych wzorów, których te algorytmy mogą używać podczas kompresji. Wysoka wydajność Brotli jest w pewnym stopniu osiągana dzięki używaniu wewnętrznego słownika.

Jednak w przypadku Brotli i ZStandard można używać niestandardowych słowników utworzonych przez użytkownika, które zawierają wzorce specyficzne dla konkretnych zasobów. W praktyce niestandardowy słownik to zewnętrzny plik, który można zastosować do dowolnego wejścia. Słowniki mogą być bardzo szczegółowe i dotyczyć kodu produkcyjnego aplikacji lub dowolnej treści. To, jak dobrze dany słownik pasuje do danych wejściowych, może mieć duży wpływ na ogólną skuteczność kompresji. Słowniki, które są bardzo podobne do treści wejściowych, będą dawać wyniki o wyższych współczynnikach kompresji niż słowniki z uniwersalnymi lub niepodobnymi treściami.

Oto przykład tego, jak skuteczny może być niestandardowy słownik kompresji: załóżmy, że Twoja witryna korzysta z ramy Angular, a jej aktualna wersja to 1.7.9. Ta wersja frameworka Angular ma rozmiar około 172 KiB w wersji niezdekompresowanej. Po skompresowaniu za pomocą ustawień domyślnych Brotli rozmiar pliku wynosi około 53 KiB. Daje to współczynnik kompresji wynoszący prawie 70%. Załóżmy jednak, że później zdecydujesz się na przejście na Angular 1.8.3. Ta wersja Angulara ma mniej więcej taki sam rozmiar jak wersja 1.7.9, więc można się spodziewać, że współczynnik kompresji będzie podobny do tego z poprzedniej wersji.

Właśnie w takich przypadkach przydaje się słownik niestandardowy, który wykorzystuje proces znany jako kompresja delty. Polega on na tym, że do skompresowania nowszej wersji zasobu można użyć słownika poprzedniej wersji tego zasobu. W przypadku poprzedniego przykładu, jeśli skompresujesz wersję 1.8.3 Angulara, używając wersji 1.7.9 jako słownika, wynik będzie miał rozmiar nieco ponad 4 KiB. Współczynnik kompresji wynosi blisko 98%. Jak widać, słowniki kompresji mogą mieć duży wpływ na wydajność wczytywania, a ich skuteczność została już sprawdzona w praktyce.

Jednak wdrożenie tego procesu w internecie może być trudne. Jeśli jednak użyjesz słownika do skompresowania zasobu, będziesz potrzebować tego samego słownika, aby rozpakować ten zasób. Ten proces był już wcześniej stosowany w internecie (w ramach SDCH), ale jego bezpieczne wdrożenie było trudne. Ta najnowsza propozycja dotycząca kompresji słownika wspólnego rozwiązuje te problemy, zapewniając jednocześnie znaczne korzyści zarówno w przypadku zasobów statycznych, jak i dynamicznych.

Jak Chrome reklamuje obsługę udostępnionych słowników

Wszystkie przeglądarki reklamują obsługiwane algorytmy kompresji w nagłówku żądania Accept-Encoding. Treść nagłówka to lista obsługiwanych kodowań rozdzielona przecinkami:

Accept-Encoding: gzip, br, zstd

Ten nagłówek Accept-Encoding informuje, że przeglądarka, która wysyła żądanie zasobu, obsługuje algorytmy kompresji gzip, Brotli i ZStandard. Serwer WWW odpowiadający na żądanie może następnie zdecydować, którego algorytmu użyć w odpowiedzi na to żądanie.

Jeśli włączona jest obsługa wspólnego słownika, a w przypadku danego zasobu dostępny jest odpowiedni słownik, do nagłówka Accept-Encoding dodawane są dodatkowe tokeny. Te tokeny to br-d dla Brotli i zstd-d dla Zstandard. Chrome będzie też zawierać hasz dostępnego słownika, o którym mowa w następnym punkcie.

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

Jeśli serwer WWW jest skonfigurowany tak, aby rozpoznawać ten token i słownik, może odpowiedzieć na to żądanie zasobem skompresowanym za pomocą słownika dla odpowiedniego kodowania. Sposób, w jaki to osiągnąć, zależy od tego, czy żądanie dotyczy zasobu statycznego czy dynamicznego.

Kompresja słownika wspólnego w przypadku zasobów statycznych

Zasób strony statycznej zawsze zwraca tę samą odpowiedź na żądanie dotyczące adresu URL. Przykładami zasobów statycznych strony, które można skompresować, są pliki JavaScript i CSS. Te zasoby są zwykle wersjonowane w jakiś sposób na potrzeby pamięci podręcznej. Czasami w nazwie pliku znajduje się hasz zawartości (np. styles.abcd1234.css) lub jest stosowana inna metoda tworzenia odcisku palca zasobu. Te typy zasobów są idealne do kompresji delty, którą zapewniają wspólne słowniki, ponieważ zasoby statyczne są często przechowywane w pamięci podręcznej przez długi czas i zwykle są aktualizowane z pewną częstotliwością.

Aby podać słownik dla zasobu statycznego, ustaw nagłówek odpowiedzi Use-As-Dictionary. Nagłówek przyjmuje jedną z kilku par klucz-wartość, ale jedyną wymaganą jest match, która akceptuje składnię URLPattern określając ścieżkę zasobu, w którym należy użyć słownika:

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

Nagłówek Use-As-Dictionary to mechanizm, który ma zastosowanie do przyszłych wersji zasobu, które pasują do określonego w nim wzorca. Załóżmy, że Twoja witryna zawiera wszystkie style w jednym pliku CSS. Dla uproszczenia przyjmijmy, że pierwsza wersja tego zasobu znajduje się pod adresem /dist/styles.v1.css i jest wysyłana z nagłówkiem odpowiedzi Use-As-Dictionary zawierającym wartość match równą /dist/styles.*.css.

Po pewnym czasie aktualizujesz plik CSS witryny i wysyłasz nową wersję, która znajduje się pod adresem /dist/styles.v2.css. Ponieważ wartość match użyta w nagłówku odpowiedzi Use-As-Dictionary z poprzedniej wersji ma zastosowanie do tego żądania, przeglądarka wyśle nagłówek Available-Dictionary zawierający hasz słownika zakodowany jako sekwencja bajtów pola strukturalnego:

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

W tym momencie to serwer musi skonfigurować kompresję, aby zapewnić użycie słownika dopasowywania. Następnie zostanie wysłany skompresowany zasób z tym słownikiem, a do jego dekompresji zostanie użyty dostępny słownik w pamięci podręcznej przeglądarki użytkownika.

Jeśli często wysyłasz nowy kod swojej witryny, kompresja delta może być bardzo przydatna. Proces ten jest jednak elastyczny. Jeśli przeglądarka nie wykryje, że słownik jest dostępny w pamięci podręcznej przeglądarki użytkownika, nie określi dodatkowych tokenów br-d ani zstd-d w nagłówku Accept-Encoding. W takim przypadku stosuje się standardowy proces kompresji.

Kompresja wspólnego słownika w przypadku zasobów dynamicznych

Kompresja wspólnego słownika może też przynieść korzyści w przypadku zasobów dynamicznych. Zasoby dynamiczne to takie, które zmieniają się w zależności od kontekstu. Przykładem może być strona internetowa z wiadomościami, której strona główna jest często aktualizowana, np. w przypadku najnowszych wiadomości. Dokumenty HTML są często zasobami dynamicznymi. W takich przypadkach słownik może zawierać większość wspólnej struktury HTML i kod szablonu witryny, co prowadzi do skompresowania stron, na których wysyłane są tylko unikalne części każdej strony.

Ze względu na charakter zasobów generowanych dynamicznie słownik musi zostać wczytany na kliencie na potrzeby późniejszego użycia. Wczytywanie słownika z wyprzedzeniem oznacza, że stosowanie kompresji słownika współdzielonego do zasobów dynamicznych jest niepewne. W takich przypadkach można mieć nadzieję, że witryna będzie miała wystarczającą liczbę użytkowników, aby koszt słownika mógł zostać rozłożony na dużą liczbę nawigacji. Jeśli zdecydujesz się na to, najpierw musisz określić lokalizację słownika za pomocą elementu <link> w kodzie HTML strony:

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

Gdy Chrome napotka element <link>, może pobrać słownik, gdy strona jest nieaktywna, i z małym priorytetem, aby uniknąć rywalizacji o przepustowość. Odpowiedź dotycząca samego słownika musi zawierać nagłówek Use-As-Dictionary i wskazywać ścieżkę dynamicznego zasobu, do której się odnosi:

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

Od tego momentu proces jest w dużej mierze taki sam jak w przypadku zasobów statycznych. Przeglądarka zobaczy, że sam słownik dotyczy pasujących zasobów, i dołączy do żądania nagłówek Available-Dictionary z haszem zawartości słownika, podobnie jak w przypadku przepływu zasobów statycznych opisanego wcześniej.

Kompresowanie zasobów statycznych w czasie kompilacji

Jeśli znasz narzędzia do tworzenia pakietów, prawdopodobnie wiesz też, że mają one różne wtyczki, które mogą kompresować zasoby w czasie kompilacji, a następnie udostępniać te skompresowane zasoby. Na przykład Apache umożliwia użycie dyrektyw, aby udostępniać te wstępnie skompresowane zasoby w momencie wysłania żądania.

Większość programów do tworzenia pakietów opartych na Node.js, które obsługują kompresję, korzysta z wbudowanej biblioteki Zlib. Zlib obsługuje Brotli, a programy do tworzenia pakietów, które go używają, zwykle oferują interfejs do przekazywania opcji bezpośrednio do Zlib, który obsługuje kompresję z użyciem słownika. Oto kilka programów do tworzenia pakietów, które obsługują słowniki:

Pamiętaj, że dostępne słowniki dla danej wersji zasobu mogą używać jednej z poprzednich wersji tego zasobu. Oznacza to, że musisz przeanalizować ruch użytkowników i odpowiednio zaplanować działania. Staraj się zachować równowagę i tworzyć zasoby, które w jak największym stopniu będą przydatne dla jak największej liczby powracających użytkowników. Dostawcy usług CDN eksperymentują obecnie z kompresją w ramach wspólnego słownika. Żadna implementacja nie jest jeszcze dostępna publicznie, ale spodziewamy się, że się to zmieni.

Spróbuj!

Połączenie kompresji wspólnego słownika z dotychczasowymi możliwościami kompresji przeglądarki może znacznie poprawić wydajność wczytywania w przypadku witryn, które często otrzymują zaktualizowany kod produkcyjny i odnotowują znaczny ruch ze strony powracających użytkowników. Jeśli chcesz wypróbować kompresję w ramach wspólnego słownika, masz 2 opcje:

  1. Jeśli chcesz samodzielnie poeksperymentować z kompresją słownika współdzielonego, aby poznać jej działanie, możesz włączyć eksperymentalną funkcję Transport słownika kompresji na stronie chrome://flags.
  2. Jeśli chcesz wypróbować tę funkcję na stronie produkcyjnej i sprawdzić, jak kompresja wspólnego słownika może pomóc prawdziwym użytkownikom, zarejestruj się na okres próbny wersji źródłowej, aby uzyskać token, i przeczytaj informacje o tym, jak działają wersje próbne wersji źródłowej.

Podsumowanie

Jesteśmy bardzo podekscytowani tym ważnym postępem w technologii kompresji w internecie i tym, jak może przyspieszyć działanie istniejących aplikacji, z których ludzie korzystają na co dzień. Zachęcamy do wypróbowania tej funkcji. Najważniejsze jest to, że chcielibyśmy poznać Twoją opinię. Jeśli znajdziesz błąd, zgłoś go na stronie crbug.com. Dodatkowe zasoby i narzędzia znajdziesz na stronie use-as-dictionary.com. Jeśli chcesz dowiedzieć się więcej o tym, jak to działa, przeczytaj ten przewodnik.