I limiti di memoria del browser durante l'elaborazione dei file
Il mio file è solo 15 MB. Perché la scheda ha esaurito la memoria?
Il file su disco è la versione compressa
L'equivoco sta tutto in una frase: il numero che vedi nel gestore file è la dimensione dei dati compressi, e niente può essere elaborato finché resta compresso. Per ridimensionare, ricomprimere, convertire o analizzare un'immagine bisogna prima decodificarla in pixel grezzi, e i pixel grezzi sono enormi.
Il calcolo è semplice. In memoria un pixel occupa di norma quattro byte: rosso, verde, blu e alfa. Una fotografia da 4000 × 3000 sono dodici milioni di pixel, quindi la bitmap decodificata pesa circa 48 MB. Il JPEG di partenza poteva essere di 4 MB. Il file è cresciuto di dodici volte prima ancora che il lavoro cominciasse.
| Dimensioni | Pixel | Bitmap decodificata |
|---|---|---|
| 1920 × 1080 | 2,1 milioni | circa 8 MB |
| 4000 × 3000 | 12 milioni | circa 48 MB |
| 6000 × 4000 | 24 milioni | circa 96 MB |
| 10000 × 10000 | 100 milioni | circa 400 MB |
E una copia sola non basta mai
Una pipeline realistica tiene in memoria più copie contemporaneamente: i byte compressi in ingresso, la bitmap sorgente decodificata, una bitmap di uscita alle nuove dimensioni, i buffer interni dell'encoder e il risultato compresso. Uno strumento che mostra anche un'anteprima ne tiene un'altra. Per la fotografia da 4000 × 3000 dell'esempio, un picco di occupazione fra i due e i trecento megabyte è del tutto normale, per un file che sembrava da 4 MB.
La rasterizzazione dei PDF si comporta allo stesso modo, pagina per pagina: una pagina A4 renderizzata a 300 DPI è circa 2480 × 3508 pixel, cioè circa 35 MB una volta decodificata, e uno strumento che renderizza più pagine insieme moltiplica quel numero. Il video è ancora peggio, perché un decodificatore deve tenere residenti più fotogrammi di riferimento nello stesso momento.
Dove stanno i tetti reali
- Il budget di memoria di una scheda lo decide il browser, non il sito, ed è inferiore alla memoria installata sulla macchina. Si restringe anche quando le altre schede sono impegnate.
- I moduli WebAssembly costruiti sul comune modello di memoria a 32 bit possono indirizzare al massimo quattro gibibyte, e spesso i browser ne concedono molto meno per ogni istanza.
- I singoli buffer hanno una lunghezza massima propria, ben al di sotto della memoria totale che una pagina può usare.
- I sistemi operativi mobili terminano una scheda che cresce troppo, senza avvisi e senza un errore che la pagina possa intercettare.
- La memoria grafica è un bacino separato e più piccolo. Un canvas più grande della dimensione massima della piattaforma semplicemente non funziona, per quanta memoria di sistema sia libera.
Nessuno di questi limiti è pubblicato come un numero unico da consultare, perché dipendono dal browser, dalla versione, dal dispositivo e da cos'altro è in esecuzione. È qui la difficoltà vera: uno strumento non può chiedere quanta memoria gli è concessa.
Perché il telefono è il caso più severo
I telefoni hanno meno memoria fisica, nessuno swap nel senso desktop del termine e un sistema operativo aggressivo nel riprendersela dai processi in background. Una scheda del browser diventa un processo in background nell'istante in cui rispondi a un messaggio. I browser mobili tengono quindi budget più stretti e scartano una scheda più in fretta, e quello scarto ti appare di solito come la pagina che si ricarica e perde il lavoro fatto, non come un errore.
La conseguenza pratica è che un lavoro che si conclude su un portatile può essere impossibile su un telefono, con lo stesso file. Non è un difetto dello strumento. È un limite dell'hardware, e la risposta onesta è dirlo prima di cominciare invece di andare in crash a metà strada.
Come si comporta uno strumento attento
- Stima l'occupazione di memoria a partire dalle dimensioni decodificate prima di allocare qualsiasi cosa, e rifiuta un lavoro che chiaramente non ci starà.
- Su un dispositivo limitato elabora un file alla volta invece di far girare un lotto in parallelo.
- Trasferisce i buffer fra la pagina e i suoi worker invece di copiarli, così un file grande non esiste in due copie.
- Rilascia ogni risultato appena è stato scritto e revoca gli URL temporanei che altrimenti terrebbero in vita i dati.
- Elabora in streaming pagina per pagina o fotogramma per fotogramma dove il formato lo consente, invece di caricare in memoria un documento intero.
- Pone un tetto al numero di pixel che accetta, ed è anche ciò che impedisce a un file piccolo, ma che si espande in un canvas enorme, di far cadere la scheda.
Cosa puoi fare quando un lavoro fallisce
- Chiudi le altre schede. Competono per lo stesso budget, e i browser non lo dividono in modo equo.
- Elabora meno file per volta. Una coda da uno è più lenta e ha molte più probabilità di arrivare in fondo.
- Riduci prima le dimensioni. Dimezzare il lato lungo porta la memoria occupata a un quarto, ed è spesso ciò che volevi comunque.
- Dividi un PDF grande ed elabora le parti.
- Passa a una macchina desktop per i lavori più grandi. Non è un fallimento dell'elaborazione locale: è l'uso corretto dell'hardware che hai.
- Riavvia il browser se una scheda è aperta da giorni. Le schede aperte a lungo accumulano memoria che un ricaricamento libera.
Il limite di qualsiasi stima
I browser espongono solo un'indicazione approssimativa della memoria disponibile, e alcuni non espongono proprio nulla. Qualunque cifra ti mostri uno strumento locale è quindi una stima costruita sulle dimensioni del file stesso e su un modello prudente della pipeline, non una lettura presa dal sistema operativo. Serve a decidere se tentare un lavoro. Non è la promessa che quel lavoro andrà a buon fine, perché il fattore decisivo — cosa farà il resto del dispositivo nei prossimi trenta secondi — non è qualcosa che una pagina web possa vedere.
Strumenti utili
Fonti
- W3C — WebAssembly Core Specification, memory model
- W3C — Device Memory API, and why the value is coarse
- WHATWG — HTML Standard, transferable objects