Verbeter de compressie-efficiëntie met gedeelde woordenboeken

Gepubliceerd: 6 maart 2024

Datacompressie is een beproefde techniek voor prestatieoptimalisatie die de grootte van relevante paginabronnen verkleint. Het was lange tijd gebruikelijk om op webservers voornamelijk gzip te gebruiken om tekstgebaseerde paginabronnen zoals HTML-, CSS- en JavaScript-bestanden te comprimeren en naar de client te sturen, waar ze vervolgens konden worden gedecomprimeerd. Het resultaat is snellere laadtijden voor de bronnen zonder de beoogde werking van de pagina te beïnvloeden.

Hoewel gzip op zichzelf zeer effectief is, zijn er de afgelopen jaren verdere verbeteringen in webcompressie gerealiseerd. In 2016 werd het Brotli-algoritme in Chrome geïntroduceerd, wat over het algemeen betere compressieverhoudingen opleverde voor geschikte bronnen. Eind 2017 ondersteunden alle moderne browsers Brotli en werd de serverondersteuning ervoor steeds gangbaarder. Recentelijk heeft Chrome ook ZStandard-compressie geïntroduceerd .

Maar daar stopt het werk niet! Het Chrome-team heeft gewerkt aan het bruikbaar maken van gedeelde woordenboeken op het web, die nu beschikbaar zijn in een Origin-proefversie voor zowel Brotli als ZStandard . Gedeelde woordenboeken kunnen de compressie van Brotli en ZStandard aanvullen en aanzienlijk hogere compressieverhoudingen leveren voor websites die regelmatig code-updates publiceren, en kunnen in sommige gevallen zelfs compressieverhoudingen van 90% of hoger bereiken. In dit artikel wordt dieper ingegaan op hoe gedeelde woordenboeken werken en hoe je je kunt registreren voor de Origin-proefversies om ze voor Brotli en ZStandard op je website te gebruiken. Je kunt ook deze video bekijken:

Gedeelde woordenboeken uitgelegd

Compressie is een proces waarbij redundante sequenties in een invoer worden gevonden en die informatie wordt gebruikt om een ​​veel kleinere uitvoer te creëren, die later weer kan worden teruggedraaid. Compressie werkt goed op het web omdat het de laadtijden van resources aanzienlijk verkort. Zowel Brotli als ZStandard kunnen hun effectiviteit verder verhogen door gebruik te maken van een compressiewoordenboek , een verzameling van extra patronen die deze algoritmen tijdens de compressie kunnen gebruiken. De hoge efficiëntie van Brotli wordt zelfs gedeeltelijk bereikt door het gebruik van een intern woordenboek.

Met Brotli en ZStandard kunnen echter aangepaste , door de gebruiker samengestelde woordenboeken worden gebruikt die patronen bevatten die specifiek zijn voor bepaalde bronnen. In de praktijk is een aangepast woordenboek een extern bestand dat op elke invoer kan worden toegepast. Woordenboeken kunnen zeer specifiek zijn voor de productiecode van een applicatie, of in principe voor elke inhoud. De mate waarin een bepaald woordenboek van toepassing is op de invoer kan een grote invloed hebben op de algehele compressie-efficiëntie. Woordenboeken die sterk lijken op de inhoud van een invoer zullen uitvoer opleveren met een hogere compressieverhouding dan woordenboeken met generieke of afwijkende inhoud.

Hier is een voorbeeld van hoe effectief een aangepast compressiewoordenboek kan zijn: stel dat uw website gebruikmaakt van het Angular-framework en de huidige versie die u gebruikt is versie 1.7.9. Deze versie van het Angular-framework is ongeveer 172 KiB groot in ongecomprimeerde vorm. Gecomprimeerd met de standaardinstellingen van Brotli, wordt de grootte ongeveer 53 KiB. Dit levert een compressieverhouding van bijna 70% op. Stel dat u later besluit te upgraden naar Angular 1.8.3. Aangezien deze versie van Angular ongeveer even groot is als versie 1.7.9, kunt u vrijwel dezelfde compressieverhouding verwachten als bij de vorige versie.

Hier kan een aangepast woordenboek van pas komen door middel van deltacompressie . Hierbij wordt een woordenboek van een eerdere versie van een resource gebruikt om een ​​latere versie te comprimeren. In het vorige voorbeeld: als je versie 1.8.3 van Angular comprimeert met versie 1.7.9 als woordenboek, is de resulterende bestandsgrootte iets meer dan 4 KiB. Dit komt neer op een compressieverhouding van bijna 98% . Het is duidelijk dat compressiewoordenboeken een grote impact kunnen hebben op de laadprestaties, en hun effectiviteit is al bewezen in praktijktoepassingen !

Het is echter een uitdaging om deze workflow op het web te laten werken. Het probleem is dat als je een woordenboek gebruikt om een ​​bron te comprimeren, je datzelfde woordenboek ook nodig hebt om de bron te decomprimeren . Deze workflow is al eerder op het web geprobeerd – met name SDCH – maar was lastig veilig te implementeren. Dit nieuwste voorstel voor compressie met een gedeeld woordenboek pakt die problemen aan en biedt tegelijkertijd aanzienlijke voordelen voor zowel statische als dynamische bronnen.

Hoe Chrome de ondersteuning voor gedeelde woordenboeken aankondigt

Alle browsers geven via de Accept-Encoding requestheader aan welke compressiealgoritmen ze ondersteunen. De inhoud van de header is een door komma's gescheiden lijst van ondersteunde coderingen:

Accept-Encoding: gzip, br, zstd

Deze specifieke Accept-Encoding header geeft aan dat de browser die de bron opvraagt ​​de compressiealgoritmen gzip, Brotli en ZStandard ondersteunt. Een webserver die op het verzoek reageert, kan vervolgens bepalen welk algoritme te gebruiken.

Wanneer ondersteuning voor gedeelde woordenboeken is ingeschakeld en er een relevant woordenboek beschikbaar is voor een bron, worden extra tokens toegevoegd aan de Accept-Encoding header. Deze tokens zijn br-d voor Brotli en zstd-d voor Zstandard. Chrome voegt ook de hash van een beschikbaar woordenboek toe, wat hierna wordt besproken.

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

Als een webserver is geconfigureerd om dit token te herkennen, en het woordenboek herkent, kan de server op dat verzoek reageren met een bron die is gecomprimeerd met behulp van het woordenboek voor de betreffende codering. Hoe dit in de praktijk wordt bereikt, hangt af van of het verzoek betrekking heeft op een statische of dynamische bron.

Gedeelde woordenboekcompressie voor statische bronnen

Een statische paginabron is een bron die altijd dezelfde respons oplevert voor een opgevraagde URL. Veelvoorkomende voorbeelden van comprimeerbare statische paginabronnen zijn JavaScript- en CSS-bestanden. Deze bronnen worden doorgaans op een of andere manier van versiebeheer voorzien voor cachingdoeleinden – soms met een hash van de inhoud van het bestand in de bestandsnaam (bijvoorbeeld styles.abcd1234.css ), of een andere methode om de bron te identificeren. Deze brontypen zijn zeer geschikt voor de delta-compressie die gedeelde woordenboeken bieden, omdat statische bronnen vaak langdurig in de cache worden opgeslagen en regelmatig worden bijgewerkt.

Voor een statische resource kan een woordenboek worden opgegeven door de Use-As-Dictionary responseheader in te stellen. De header accepteert een van de verschillende sleutel/waarde-paren, maar de enige verplichte is match , die URLPattern syntaxis accepteert om het resourcepad te specificeren waar het woordenboek moet worden gebruikt:

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

Beschouw de Use-As-Dictionary header als een mechanisme dat van toepassing is op toekomstige versies van een bron die overeenkomen met het patroon dat erin is gespecificeerd. Stel dat uw website al zijn stijlen in één CSS-bestand verzendt. Laten we voor de eenvoud aannemen dat de eerste versie van die bron zich bevindt op /dist/styles.v1.css en wordt verzonden met een Use-As-Dictionary antwoordheader match de waarde /dist/styles.*.css .

Na enige tijd werk je de CSS van je website bij en verstuur je een nieuwe versie die te vinden is op /dist/styles.v2.css . Omdat de match die in de Use-As-Dictionary responsheader van de vorige versie werd gebruikt ook van toepassing is op dit verzoek, stuurt de browser een Available-Dictionary header met een hash van het woordenboek, gecodeerd als een gestructureerde byte-reeks .

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

Vanaf dit punt is het aan de server om de compressie aan zijn kant te configureren, zodat het overeenkomende woordenboek wordt gebruikt. De met dat woordenboek gecomprimeerde bron wordt vervolgens verzonden en het beschikbare woordenboek in de browsercache van de gebruiker wordt gebruikt om deze te decomprimeren.

Als je regelmatig nieuwe code voor je website uitbrengt, kan delta-compressie een groot verschil maken. Het proces is echter flexibel. Als de browser niet vaststelt dat er een woordenboek in de cache van de gebruiker aanwezig is, worden de extra tokens br-d of zstd-d niet in de Accept-Encoding header vermeld. In dat geval wordt de standaard compressieprocedure toegepast.

Gedeelde woordenboekcompressie voor dynamische bronnen

Dynamische bronnen kunnen ook profiteren van compressie met een gedeeld woordenboek. Dynamische bronnen zijn bronnen die veranderen op basis van de context, zoals bijvoorbeeld een nieuwswebsite waar de hoofdpagina regelmatig wordt bijgewerkt wanneer er nieuws is. HTML-documenten zijn vaak dynamische bronnen. In dergelijke gevallen kan het woordenboek het grootste deel van de gemeenschappelijke HTML-structuur en sjablooncode van de site bevatten, wat leidt tot gecomprimeerde pagina's waarbij alleen de unieke onderdelen van elke pagina worden verzonden.

Vanwege de aard van dynamisch gegenereerde bronnen moet een woordenboek aan de clientzijde worden geladen voor later gebruik. Het vooraf laden van een woordenboek betekent dat het toepassen van gedeelde woordenboekcompressie op dynamische bronnen speculatief is. De hoop is in dergelijke gevallen dat uw website voldoende verkeer ontvangt, zodat de kosten van het woordenboek over een groot aantal navigaties kunnen worden terugverdiend. Mocht u besluiten dit te proberen, dan is de eerste stap het specificeren van de locatie van het woordenboek door middel van een <link> -element in de HTML van uw pagina:

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

Wanneer Chrome dit <link> -element tegenkomt, kan het de dictionary ophalen zodra de pagina inactief is, en met een lage prioriteit om bandbreedteconflicten te voorkomen. Het antwoord voor de dictionary zelf moet een Use-As-Dictionary header bevatten en aangeven op welk dynamisch resourcepad deze van toepassing is:

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

Vanaf hier is het proces grotendeels hetzelfde als voor statische bronnen. De browser ziet dat het woordenboek van toepassing is op overeenkomende bronnen en voegt een Available-Dictionary header toe aan het verzoek met een hash van de inhoud van het woordenboek, wederom vergelijkbaar met het eerder beschreven proces voor statische bronnen.

Comprimeer statische resources tijdens het compileren.

Als je bekend bent met bundlers, ben je wellicht ook bekend met de verschillende plugins die ervoor bestaan ​​en die resources tijdens het buildproces kunnen comprimeren en vervolgens die gecomprimeerde resources kunnen aanbieden. Apache biedt bijvoorbeeld de mogelijkheid om via directives die vooraf gecomprimeerde resources direct bij het verzoek aan te bieden .

De meeste Node.js-gebaseerde bundlers die compressie ondersteunen, gebruiken de ingebouwde Zlib-bibliotheek van Node.js. Zlib biedt ondersteuning voor Brotli en bundlers die ervan gebruikmaken, bieden doorgaans een interface om opties rechtstreeks aan Zlib door te geven, wat compressie met behulp van dictionaries ondersteunt . Hier zijn een paar bundlers die het gebruik van dictionaries ondersteunen:

Houd er rekening mee dat beschikbare woordenboeken voor een bepaalde versie van een resource een van de eerdere versies van die resource kunnen gebruiken. Dit betekent dat u het gebruikersverkeer moet analyseren en dienovereenkomstig moet plannen. Streef naar een evenwicht en genereer resources die zoveel mogelijk terugkerende gebruikers ten goede komen. CDN-providers experimenteren momenteel met gedeelde woordenboekcompressie. Er zijn nog geen implementaties beschikbaar voor publiek gebruik, maar we verwachten dat dit zal veranderen!

Probeer het eens!

Het integreren van shared dictionary compression met de bestaande compressiemogelijkheden van de browser kan de laadprestaties aanzienlijk verbeteren voor websites die regelmatig bijgewerkte productiecode publiceren en veel verkeer van terugkerende bezoekers ontvangen. Als u shared dictionary compression wilt uitproberen, heeft u twee opties:

  1. Als je zelf wilt experimenteren met het comprimeren van gedeelde woordenboeken om te zien hoe het werkt, kun je de experimentele functie 'Compression dictionary transport' inschakelen op de pagina chrome://flags .
  2. Als je dit wilt uitproberen op je productiewebsite en wilt zien hoe gedeelde woordenboekcompressie echte gebruikers ten goede kan komen, meld je dan aan voor de Origin-proef om een ​​token te krijgen en lees meer over hoe Origin-proeven werken .

Conclusie

We zijn erg enthousiast over deze belangrijke vooruitgang in compressietechnologie op het web en hoe veel sneller bestaande applicaties die mensen dagelijks gebruiken hierdoor kunnen worden. We moedigen je aan om het uit te proberen en, nog belangrijker, we horen graag je mening ! Als je een bug vindt, meld deze dan op crbug.com . Voor extra informatie en tools kun je terecht op use-as-dictionary.com . En als je meer wilt weten over hoe het allemaal werkt, is de uitleg een goede volgende stap!