Browserens hukommelsesgrænser ved filbehandling
Min fil fylder kun 15 MB. Hvorfor løb fanen tør for hukommelse?
Filen på disken er den komprimerede udgave
Hele misforståelsen ligger i én sætning: det tal, du ser i filhåndteringen, er størrelsen på de komprimerede data, og intet kan behandles, mens det er komprimeret. For at skalere, komprimere igen, konvertere eller analysere et billede skal det først afkodes til rå pixels, og rå pixels er enorme.
Regnestykket er simpelt. En pixel i hukommelsen fylder normalt fire bytes — rød, grøn, blå og alfa. Et fotografi på 4000 × 3000 er tolv millioner pixels, så den afkodede bitmap fylder cirka 48 MB. Den JPEG, det kom fra, fyldte måske 4 MB. Filen voksede med en faktor tolv, før arbejdet overhovedet gik i gang.
| Dimensioner | Pixels | Afkodet bitmap |
|---|---|---|
| 1920 × 1080 | 2,1 millioner | cirka 8 MB |
| 4000 × 3000 | 12 millioner | cirka 48 MB |
| 6000 × 4000 | 24 millioner | cirka 96 MB |
| 10000 × 10000 | 100 millioner | cirka 400 MB |
Og én kopi er aldrig nok
Et realistisk forløb holder flere kopier ad gangen: de komprimerede inputbytes, den afkodede kildebitmap, en outputbitmap i de nye dimensioner, encoderens interne buffere og det komprimerede resultat. Et værktøj, der også viser dig et eksempel, holder endnu en. For fotografiet på 4000 × 3000 ovenfor er et hukommelsesforbrug på to til tre hundrede megabytes på toppen helt almindeligt, for en fil der så ud til at fylde 4 MB.
PDF-rasterisering opfører sig på samme måde, side for side: en A4-side gengivet ved 300 DPI er cirka 2480 × 3508 pixels, omkring 35 MB afkodet, og et værktøj, der gengiver flere sider ad gangen, ganger det op. Video er værre igen, fordi en dekoder skal have flere referencebilleder liggende samtidig.
Hvor de reelle lofter ligger
- En fanes hukommelsesbudget sættes af browseren, ikke af sitet, og det er mindre end maskinens installerede hukommelse. Det skrumper også, når andre faner har travlt.
- WebAssembly-moduler bygget til den udbredte 32-bit hukommelsesmodel kan højst adressere fire gibibytes, og browsere tillader ofte betydeligt mindre end det per instans.
- Enkelte buffere har deres egen maksimale længde, som ligger et godt stykke under den samlede hukommelse, en side må bruge.
- Styresystemer på telefoner lukker en fane, der vokser sig for stor, uden varsel og uden en fejl, siden kan opfange.
- Grafikhukommelsen er en separat og mindre pulje. En canvas, der er større end platformens maksimale mål, fejler simpelthen, uanset hvor meget systemhukommelse der er fri.
Ingen af dem er offentliggjort som ét tal, du kan slå op, for de afhænger af browseren, versionen, enheden og af, hvad der ellers kører. Det er den reelle vanskelighed: et værktøj kan ikke spørge, hvor meget hukommelse det må bruge.
Hvorfor telefoner er det strenge tilfælde
Telefoner har mindre fysisk hukommelse, ingen swap i den forstand, man kender fra computere, og et styresystem, der er aggressivt med at tage hukommelsen tilbage fra baggrundsprocesser. En browserfane er en baggrundsproces i det øjeblik, du svarer på en besked. Mobilbrowsere holder derfor strammere budgetter og er hurtigere til at kassere en fane, og for dig ser den kassering som regel ud, som om siden genindlæses og mister dit arbejde, snarere end som en fejl.
Den praktiske konsekvens er, at en opgave, der bliver færdig på en bærbar, kan være umulig på en telefon med den samme fil. Det er ikke en fejl i værktøjet. Det er en hardwaregrænse, og det ærlige svar er at sige det, før man går i gang, frem for at bryde sammen halvvejs.
Sådan opfører et omhyggeligt værktøj sig
- Det vurderer hukommelsesforbruget ud fra de afkodede dimensioner, før det allokerer noget, og afviser en opgave, der tydeligvis ikke kan være der.
- Det behandler én fil ad gangen på en begrænset enhed i stedet for at køre en hel bunke parallelt.
- Det overfører buffere mellem siden og dens workers frem for at kopiere dem, så en stor fil ikke findes to gange.
- Det frigiver hvert resultat, så snart det er skrevet, og tilbagekalder de midlertidige URL'er, der ellers ville holde dataene i live.
- Det behandler side for side eller billede for billede, hvor formatet tillader det, i stedet for at indlæse et helt dokument i hukommelsen.
- Det sætter et loft over det antal pixels, det tager imod, og det er også det, der forhindrer en lille fil, der folder sig ud til en enorm canvas, i at tage fanen med sig.
Hvad du kan gøre, når en opgave fejler
- Luk andre faner. De konkurrerer om det samme budget, og browsere deler det ikke ligeligt.
- Behandl færre filer ad gangen. En kø på én er langsommere og har langt større chance for at blive færdig.
- Reducer dimensionerne først. At halvere den længste side firedeler hukommelsesforbruget, og det er ofte alligevel det, du ville.
- Del en stor PDF op, og behandl delene.
- Gå over på en stationær eller bærbar maskine til de største opgaver. Det er ikke et nederlag for lokal behandling; det er den rigtige brug af den hardware, du har.
- Genstart browseren, hvis en fane har været åben i dagevis. Langtidsåbne faner samler hukommelse op, som en genindlæsning frigiver.
Grænsen for ethvert estimat
Browsere afslører kun et groft fingerpeg om den tilgængelige hukommelse, og nogle afslører slet ingenting. Ethvert tal, et lokalt værktøj viser dig, er derfor et estimat bygget på filens egne dimensioner og en konservativ model af forløbet, ikke en aflæsning fra styresystemet. Det er nyttigt til at afgøre, om man skal forsøge sig med en opgave. Det er ikke et løfte om, at opgaven bliver færdig, for den afgørende faktor — hvad resten af enheden foretager sig i de næste tredive sekunder — er ikke noget, en webside kan se.
Værktøjer til dette
Kilder
- W3C — WebAssembly Core Specification, memory model
- W3C — Device Memory API, and why the value is coarse
- WHATWG — HTML Standard, transferable objects