Geheugenlimieten van de browser bij het verwerken van bestanden
Mijn bestand is maar 15 MB. Waarom komt het tabblad dan geheugen tekort?
Het bestand op schijf is de gecomprimeerde versie
Hier zit het hele misverstand in één zin: het getal dat je in de bestandsbeheerder ziet, is de omvang van de gecomprimeerde data, en er valt niets te verwerken zolang die gecomprimeerd is. Om een afbeelding te verkleinen, opnieuw te comprimeren, te converteren of te analyseren, moet die eerst worden gedecodeerd naar ruwe pixels, en ruwe pixels zijn enorm.
Het rekenwerk is simpel. Een pixel in het geheugen is normaal gesproken vier bytes – rood, groen, blauw en alpha. Een foto van 4000 × 3000 telt twaalf miljoen pixels, dus de gedecodeerde bitmap is ongeveer 48 MB. De JPEG waar die uit kwam was misschien 4 MB. Het bestand werd twaalf keer zo groot nog voordat er ook maar iets was gedaan.
| Afmetingen | Pixels | Gedecodeerde bitmap |
|---|---|---|
| 1920 × 1080 | 2,1 miljoen | ongeveer 8 MB |
| 4000 × 3000 | 12 miljoen | ongeveer 48 MB |
| 6000 × 4000 | 24 miljoen | ongeveer 96 MB |
| 10000 × 10000 | 100 miljoen | ongeveer 400 MB |
En één kopie is nooit genoeg
Een realistische pijplijn houdt meerdere kopieën tegelijk vast: de gecomprimeerde invoerbytes, de gedecodeerde bronbitmap, een uitvoerbitmap op de nieuwe afmetingen, de interne buffers van de encoder en het gecomprimeerde resultaat. Een tool die ook nog een voorbeeldweergave toont, houdt er nog een vast. Voor de foto van 4000 × 3000 hierboven is een piekgeheugengebruik van twee- tot driehonderd megabyte volstrekt normaal, voor een bestand dat eruitzag als 4 MB.
PDF-rasterisatie gedraagt zich net zo, pagina voor pagina: een A4-pagina gerenderd op 300 DPI is ruwweg 2480 × 3508 pixels, gedecodeerd zo'n 35 MB, en een tool die meerdere pagina's tegelijk rendert, vermenigvuldigt dat. Video is nog erger, want een decoder moet meerdere referentieframes tegelijk in het geheugen houden.
Waar de echte plafonds liggen
- Het geheugenbudget van een tabblad wordt bepaald door de browser, niet door de site, en het is kleiner dan het geïnstalleerde geheugen van de machine. Het krimpt bovendien wanneer andere tabbladen druk bezig zijn.
- WebAssembly-modules die gebouwd zijn voor het gangbare 32-bits geheugenmodel kunnen hoogstens vier gibibytes adresseren, en browsers staan per instantie vaak aanzienlijk minder toe.
- Afzonderlijke buffers hebben hun eigen maximale lengte, die ruim onder het totale geheugen ligt dat een pagina mag gebruiken.
- Mobiele besturingssystemen beëindigen een tabblad dat te groot wordt, zonder waarschuwing en zonder fout die de pagina kan opvangen.
- Grafisch geheugen is een aparte, kleinere pool. Een canvas dat groter is dan de maximale afmeting van het platform mislukt gewoon, hoeveel systeemgeheugen er ook vrij is.
Geen van deze grenzen is gepubliceerd als één getal dat je kunt opzoeken, want ze hangen af van de browser, de versie, het apparaat en wat er verder draait. Dat is de echte moeilijkheid: een tool kan niet opvragen hoeveel geheugen het mag gebruiken.
Waarom telefoons het strengste geval zijn
Telefoons hebben minder fysiek geheugen, geen swap in de desktopbetekenis van het woord, en een besturingssysteem dat dat geheugen agressief terugvordert van achtergrondprocessen. Een browsertabblad is een achtergrondproces zodra je een bericht beantwoordt. Mobiele browsers hanteren daarom krappere budgetten en gooien een tabblad sneller weg, en dat weggooien ziet er voor jou meestal uit alsof de pagina herlaadt en je werk kwijt is, niet als een foutmelding.
Het praktische gevolg is dat een klus die op een laptop afloopt, met hetzelfde bestand onmogelijk kan zijn op een telefoon. Dat is geen gebrek in de tool. Het is een hardwaregrens, en het eerlijke antwoord is dat vooraf zeggen in plaats van halverwege vastlopen.
Hoe een zorgvuldige tool zich gedraagt
- Hij schat het geheugengebruik in aan de hand van de gedecodeerde afmetingen voordat hij iets alloceert, en weigert een klus die duidelijk niet past.
- Hij verwerkt op een beperkt apparaat één bestand tegelijk in plaats van een batch parallel te draaien.
- Hij verplaatst buffers tussen de pagina en zijn workers in plaats van ze te kopiëren, zodat een groot bestand niet twee keer bestaat.
- Hij geeft elk resultaat vrij zodra het is weggeschreven, en trekt de tijdelijke URL's in die de data anders in leven zouden houden.
- Hij streamt pagina voor pagina of frame voor frame waar het formaat dat toelaat, in plaats van een heel document in het geheugen te laden.
- Hij begrenst het aantal pixels dat hij accepteert, en dat is ook wat voorkomt dat een klein bestand dat uitdijt tot een enorm canvas het tabblad meesleurt.
Wat je kunt doen als een klus mislukt
- Sluit andere tabbladen. Ze concurreren om hetzelfde budget, en browsers verdelen dat niet eerlijk.
- Verwerk minder bestanden tegelijk. Een wachtrij van één is langzamer en maakt veel meer kans om af te lopen.
- Verklein eerst de afmetingen. De langste zijde halveren brengt het geheugengebruik terug tot een kwart, en vaak is dat toch al wat je wilde.
- Splits een grote PDF en verwerk de delen.
- Ga voor de grootste klussen naar een desktopmachine. Dat is geen falen van lokale verwerking; het is het juiste gebruik van de hardware die je hebt.
- Herstart de browser als een tabblad al dagen openstaat. Langlevende tabbladen stapelen geheugen op dat bij een herlaadbeurt weer vrijkomt.
De grens van elke schatting
Browsers geven maar een grove hint over het beschikbare geheugen, en sommige geven helemaal niets. Elk getal dat een lokale tool je laat zien is daarom een schatting, opgebouwd uit de afmetingen van het bestand zelf en een behoudend model van de pijplijn, en geen uitlezing van het besturingssysteem. Het is bruikbaar om te beslissen of je een klus probeert. Het is geen belofte dat de klus afloopt, want de doorslaggevende factor – wat de rest van het apparaat de komende dertig seconden doet – kan een webpagina niet zien.
Tools hiervoor
Bronnen
- W3C — WebAssembly Core Specification, memory model
- W3C — Device Memory API, and why the value is coarse
- WHATWG — HTML Standard, transferable objects