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

Kompresja danych to sprawdzona metoda optymalizacji wydajności, która zmniejsza rozmiar odpowiednich zasobów strony. Przez jakiś czas powszechną praktyką było używanie narzędzia gzip na serwerach WWW do kompresowania często używanych zasobów tekstowych, takich jak pliki HTML, CSS i JavaScript, a następnie do wysyłania ich do klienta, gdzie zostały poddane dekompresji. W rezultacie czas wczytywania zasobów nie wpływa na prawidłowe działanie strony.

Choć program gzip samo w sobie jest bardzo skuteczny, w ostatnich latach odnotowano dalsze udoskonalenia w zakresie kompresji stron internetowych. W 2016 roku wprowadziliśmy w Chrome algorytm Brotli, który zapewnia ogólnie lepsze współczynniki kompresji kwalifikujących się zasobów. Pod koniec 2017 roku wszystkie nowoczesne przeglądarki obsługiwały Brotli, a obsługa serwerów tej technologii zaczęła być coraz bardziej powszechna. Niedawno Chrome udostępnił kompresję ZStandard.

Na tym praca się nie kończy. Zespół Chrome pracuje nad umożliwieniem korzystania ze udostępnionych słowników w internecie. Obecnie są one dostępne w ramach testowania origin zarówno w Brotli, jak i ZStandard. Udostępnione słowniki mogą uzupełniać kompresję Brotli i ZStandard, aby uzyskać znacznie wyższe współczynniki kompresji na stronach, które często przesyłają zaktualizowany kod, a w niektórych przypadkach mogą uzyskać współczynniki kompresji 90% lub lepsze. W tym poście bardziej szczegółowo opisujemy, jak działają udostępniane słowniki i jak zarejestrować się w testach origin, aby używać ich w usługach Brotli i ZStandard w swojej witrynie.

Omówienie udostępnionych słowników

Kompresja to proces znajdowania zbędnych sekwencji wejściowych i wykorzystywania ich do uzyskania znacznie mniejszych danych wyjściowych, które można później cofnąć. Kompresja dobrze działa w internecie, ponieważ znacznie skraca czas wczytywania zasobów. Zarówno Brotli, jak i ZStandard mogą jeszcze bardziej zwiększyć skuteczność dzięki wykorzystaniu słownika kompresji, który jest zbiorem dodatkowych wzorców, które te algorytmy mogą wykorzystać podczas kompresji. W rzeczywistości wysoką skuteczność Brotliego udaje się w pewnym stopniu dzięki użyciu wewnętrznego słownika.

Natomiast w przypadku słowników Brotli i ZStandard można używać niestandardowych słowników wybranych przez użytkowników, które zawierają wzorce specyficzne dla konkretnych zasobów. Słownik niestandardowy to zewnętrzny plik, który można zastosować do dowolnych danych wejściowych. Słowniki mogą być ściśle związane z kodem produkcyjnym aplikacji lub mogą być powiązane z dowolną treścią. Zastosowanie danego słownika do danych wejściowych może mieć duży wpływ na ogólną wydajność kompresji. Słowniki, które są bardzo podobne do treści danych wejściowych, zwracają dane wyjściowe o wyższych współczynnikach kompresji niż słowniki z treściami ogólnymi lub odmiennymi.

Oto przykład skuteczności niestandardowego słownika kompresji: załóżmy, że Twoja witryna korzysta z platformy Angular, a bieżąca wersja to 1.7.9. Ta wersja platformy Angular ma około 172 kiB bez kompresji. Po skompresowaniu za pomocą domyślnych ustawień Brotli rozmiar ten wynosi około 53 KiB. Daje to współczynnik kompresji niemal na poziomie 70%. Pamiętaj jednak, że zdecydujesz się później uaktualnić Angular do wersji 1.8.3. Biorąc pod uwagę, że ta wersja Angular ma mniej więcej taki sam rozmiar jak wersja 1.7.9, współczynnik kompresji można oczekiwać w przypadku poprzedniej wersji.

W takim przypadku może się przydać słownik niestandardowy, który korzysta z procesu zwanego kompresją delta, w której do skompresowania nowszej wersji można użyć słownika poprzedniej wersji zasobu. W poprzednim przykładzie, jeśli skompresujesz wersję 1.8.3 Angular za pomocą słownika w wersji 1.7.9, wynik będzie miał nieco ponad 4 KiB. Oznacza to współczynnik kompresji na poziomie prawie 98%. Oczywiście słowniki kompresji mogą mieć duży wpływ na wydajność wczytywania, a ich skuteczność została już osiągnięta w prawdziwych aplikacjach.

Jej zastosowanie w internecie wiąże się jednak z pewnym wyzwaniem. Problem polega na tym, że jeśli używasz słownika do skompresowania zasobu, musisz mieć ten sam słownik, żeby go zdekompresować. Tę funkcję próbowano już wcześniej w internecie (a mianowicie SDCH), ale jej bezpieczne wdrożenie było trudne. Najnowsza propozycja współdzielonej kompresji słownika rozwiązuje te problemy, zapewniając zarazem znaczne korzyści zarówno dla zasobów statycznych, jak i dynamicznych.

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

Wszystkie przeglądarki reklamują obsługiwane przez nie algorytmy kompresji, korzystając z nagłówka żądania Accept-Encoding. Zawartość nagłówka to rozdzielana przecinkami lista obsługiwanych kodowania:

Accept-Encoding: gzip, br, zstd

Ten konkretny nagłówek Accept-Encoding informuje, że przeglądarka wysyłająca żądanie do 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ć.

Gdy obsługa słownika udostępnionego jest włączona i dla zasobu dostępny jest odpowiedni słownik, do nagłówka Accept-Encoding dodawane są dodatkowe tokeny. Te tokeny są br-d dla Brotli i zstd-d dla Zstandard. Chrome umieszcza też wartości skrótu dostępnego słownika, który został omówiony w dalszej części tego artykułu.

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

Jeśli serwer WWW jest skonfigurowany do rozpoznawania tego tokena i rozpozna słownik, może odpowiedzieć na to żądanie przy użyciu zasobu skompresowanego za pomocą słownika na potrzeby odpowiedniego kodowania. Sposób, w jaki to zostanie osiągnięty, zależy od tego, czy żądanie dotyczy zasobu statycznego, czy dynamicznego.

Wspólna kompresja słownika zasobów statycznych

Zasób strony statycznej to taki, który zawsze generuje tę samą odpowiedź na żądanie adresu URL. Typowe przykłady możliwych do kompresji zasobów stron statycznych to pliki JavaScript i CSS. Te zasoby są zwykle w jakiś sposób przekształcane w wersje na potrzeby buforowania, czasami za pomocą skrótu zawartości pliku w nazwie pliku (na przykład styles.abcd1234.css) lub przy użyciu innej metody odcisków cyfrowych zasobu. Zasoby te doskonale nadają się do kompresji delta udostępnianej 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ą.

Słownik można określić na potrzeby zasobu statycznego, ustawiając dla niego nagłówek odpowiedzi Use-As-Dictionary. Nagłówek przyjmuje jedną z kilku par klucz/wartość, ale jedyną wymaganą w ten sposób jest parą klucz-wartość match, która akceptuje składnię URLPattern określającą ścieżkę zasobu, na której należy używać słownika:

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

Nagłówek Use-As-Dictionary to mechanizm, który odnosi się do przyszłych wersji zasobu pasującego do określonego w nim wzorca. Załóżmy więc, że Twoja witryna przesyła wszystkie style w jednym pliku CSS. Dla uproszczenia załóżmy, ż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 jakimś czasie aktualizujesz usługę porównywania cen w swojej witrynie i wysyłasz jej nową wersję na adres /dist/styles.v2.css. Wartość match użyta w nagłówku odpowiedzi Use-As-Dictionary z poprzedniej wersji ma zastosowanie do tego żądania, dlatego przeglądarka wyśle nagłówek Available-Dictionary zawierający hasz słownika zakodowany jako sekwencja bajtów w uporządkowanym polu:

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

Na tym etapie to serwer musi skonfigurować kompresję po swojej stronie, aby zapewnić używanie pasującego słownika. Zasób skompresowany za pomocą tego słownika zostanie wysłany, a do jego dekompresji zostanie użyty słownik dostępny w pamięci podręcznej przeglądarki użytkownika.

Jeśli często przesyłasz nowy kod do witryny, kompresja delta może zdziałać cuda. Jest on jednak elastyczny. Jeśli przeglądarka nie ustali, że w pamięci podręcznej przeglądarki użytkownika jest dostępny słownik, nie wskaże dodatkowych tokenów br-d ani zstd-d w nagłówku Accept-Encoding. W takim przypadku obowiązuje standardowy przepływ kompresji.

Współdzielona kompresja słownika na potrzeby zasobów dynamicznych

Zasoby dynamiczne mogą też korzystać ze wspólnej kompresji słownika. Zasoby dynamiczne to takie, które zmieniają się w zależności od kontekstu – np. witryna z wiadomościami, na której strona główna jest często aktualizowana. Dokumenty HTML są często zasobami dynamicznymi. W takich przypadkach słownik może zawierać większość typowej struktury HTML witryny oraz kod szablonu, który prowadzi do skompresowanych stron, na które wysyłane są tylko unikalne części każdej strony.

Ze względu na charakter zasobów generowanych dynamicznie słownik musi zostać wczytany w kliencie do późniejszego użycia. Załadowanie słownika z wyprzedzeniem oznacza, że zastosowanie współdzielonej kompresji słownika do zasobów dynamicznych jest spekulacyjne. W takich przypadkach mamy nadzieję, że witryna odnotowuje tak duży ruch, że koszt słownika można amortyzować w oparciu o dużą liczbę elementów nawigacyjnych. Jeśli zdecydujesz się tego użyć, najpierw określ lokalizację słownika za pomocą elementu <link> w kodzie HTML strony:

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

Gdy Chrome natrafi na ten element <link>, może pobrać słownik, gdy strona jest bezczynna, i ma niski priorytet, by uniknąć rywalizacji z przepustowością. Odpowiedź dla słownika musi zawierać nagłówek Use-As-Dictionary i określać, do której ścieżki zasobu dynamicznego ma być stosowany:

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

Przepływ tutaj jest w dużej mierze taki sam jak w przypadku zasobów statycznych. Przeglądarka zobaczy, że słownik dotyczy pasujących zasobów i dołączy do żądania nagłówek Available-Dictionary z hashtagiem zawartości słownika, podobnie jak w przypadku omówionego wcześniej przepływu zasobów statycznych.

Kompresuj zasoby statyczne w czasie kompilacji

Jeśli znasz się na pakietach, być może znasz różne wtyczki, które kompresują zasoby podczas kompilacji, a potem wyświetlają te skompresowane zasoby. Na przykład Apache umożliwia wyświetlanie tych wstępnie skompresowanych zasobów za pomocą instrukcji w momencie żądania.

Większość pakietów opartych na Node.js, które obsługują kompresję, korzysta z wbudowanej biblioteki Zlib w węźle. Zlib zapewnia wsparcie dla rozwiązań Brotli i pakietów, które z niego korzystają. Zwykle udostępniają one interfejs umożliwiający bezpośrednie przekazywanie opcji do pliku Zlib, który obsługuje kompresję opartą na słowniku. Oto kilka pakietów, które umożliwiają korzystanie ze słowników:

Pamiętaj, że słowniki dostępne dla każdej wersji zasobu mogą korzystać z dowolnej wcześniejszej wersji zasobu. Oznacza to, że musisz analizować ruch użytkowników i odpowiednio planować działania. Dąż do tego, aby zrównoważyć sytuację i generować zasoby, które zapewnią maksymalną liczbę powracających użytkowników jak największej liczbie powracających użytkowników. Dostawcy CDN eksperymentują obecnie ze współdzieloną kompresją słownika. Żadne implementacje nie są jeszcze dostępne do użytku publicznego, ale oczekujemy, że to się zmieni.

Spróbuj!

Integracja współdzielonej kompresji słownika z istniejącymi funkcjami kompresji przeglądarki może znacznie poprawić wydajność wczytywania witryn, które często wysyłają zaktualizowany kod produkcyjny i otrzymują znaczny ruch ze strony powracających użytkowników. Jeśli chcesz wypróbować kompresję słownikową, masz 2 możliwości:

  1. Jeśli chcesz samodzielnie wypróbować wspólną kompresję słownikową, aby zobaczyć, jak to działa, możesz włączyć eksperymentalną funkcję Transport słownika kompresji na stronie chrome://flags.
  2. Jeśli chcesz wypróbować tę funkcję w swojej witrynie produkcyjnej i zobaczyć, jakie korzyści może przynieść użytkownikom wspólna kompresja słownika, zarejestruj się w wersji próbnej origin, aby uzyskać token, i przeczytaj, jak działają testy origin.

Podsumowanie

Jesteśmy podekscytowani rozwojem technologii kompresji w internecie, który przyspieszy rozwój aplikacji i sprawi, że ludzie będą używać ich na co dzień. Zachęcamy do wypróbowania tej usługi, a przede wszystkim chętnie poznamy 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, skorzystaj z wyjaśnienia.