Limites de memória do navegador ao processar arquivos
Meu arquivo tem só 15 MB. Por que a aba ficou sem memória?
O arquivo no disco é a versão comprimida
O mal-entendido inteiro cabe em uma frase: o número que aparece no gerenciador de arquivos é o tamanho dos dados comprimidos, e nada pode ser processado enquanto está comprimido. Para redimensionar, recomprimir, converter ou analisar uma imagem, é preciso antes decodificá-la em pixels brutos, e pixels brutos são enormes.
A conta é simples. Um pixel na memória ocupa normalmente quatro bytes — vermelho, verde, azul e alfa. Uma fotografia de 4000 × 3000 tem doze milhões de pixels, então o bitmap decodificado ocupa cerca de 48 MB. O JPEG de onde ela veio podia ter 4 MB. O arquivo cresceu doze vezes antes de qualquer trabalho começar.
| Dimensões | Pixels | Bitmap decodificado |
|---|---|---|
| 1920 × 1080 | 2,1 milhões | cerca de 8 MB |
| 4000 × 3000 | 12 milhões | cerca de 48 MB |
| 6000 × 4000 | 24 milhões | cerca de 96 MB |
| 10000 × 10000 | 100 milhões | cerca de 400 MB |
E uma cópia nunca basta
Um pipeline realista mantém várias cópias ao mesmo tempo: os bytes comprimidos de entrada, o bitmap de origem decodificado, um bitmap de saída nas novas dimensões, os buffers internos do codificador e o resultado comprimido. Uma ferramenta que ainda mostra uma prévia mantém mais uma. Para a fotografia de 4000 × 3000 acima, um pico de uso de duzentos a trezentos megabytes é perfeitamente comum — para um arquivo que aparentava ter 4 MB.
A rasterização de PDF se comporta do mesmo jeito, página por página: uma página A4 renderizada a 300 DPI tem cerca de 2480 × 3508 pixels, algo como 35 MB decodificados, e uma ferramenta que renderiza várias páginas de uma vez multiplica isso. Vídeo é pior ainda, porque o decodificador precisa manter vários quadros de referência na memória ao mesmo tempo.
Onde ficam os tetos reais
- O orçamento de memória de uma aba é definido pelo navegador, não pelo site, e é menor que a memória instalada na máquina. Ele também diminui quando outras abas estão trabalhando.
- Módulos WebAssembly compilados para o modelo de memória de 32 bits mais comum endereçam no máximo quatro gibibytes, e os navegadores costumam permitir bem menos que isso por instância.
- Cada buffer tem um comprimento máximo próprio, bem abaixo do total de memória que a página pode usar.
- Sistemas operacionais móveis encerram uma aba que cresce demais, sem aviso e sem nenhum erro que a página consiga capturar.
- A memória gráfica é um espaço separado e menor. Um canvas maior que a dimensão máxima da plataforma simplesmente falha, por mais memória de sistema que esteja livre.
Nenhum desses limites é publicado como um número único que dá para consultar, porque todos dependem do navegador, da versão, do aparelho e do que mais está rodando. É essa a dificuldade real: uma ferramenta não tem como perguntar quanta memória pode usar.
Por que o celular é o caso mais restrito
Celulares têm menos memória física, não têm swap no sentido que existe no desktop e rodam um sistema operacional agressivo em retomar memória de processos em segundo plano. Uma aba do navegador vira um processo em segundo plano no instante em que você responde uma mensagem. Por isso os navegadores móveis trabalham com orçamentos mais apertados e descartam abas mais rápido — e, para você, esse descarte costuma parecer a página recarregando e perdendo seu trabalho, não um erro.
A consequência prática é que uma tarefa que termina num notebook pode ser impossível num celular com o mesmo arquivo. Isso não é defeito da ferramenta. É um limite de hardware, e a resposta honesta é avisar antes de começar, em vez de travar no meio do caminho.
Como se comporta uma ferramenta cuidadosa
- Ela estima o uso de memória a partir das dimensões decodificadas antes de alocar qualquer coisa e recusa uma tarefa que claramente não vai caber.
- Ela processa um arquivo por vez em um aparelho limitado, em vez de rodar um lote em paralelo.
- Ela transfere os buffers entre a página e os workers em vez de copiá-los, para que um arquivo grande não exista duas vezes.
- Ela libera cada resultado assim que ele é gravado e revoga as URLs temporárias que, de outro modo, manteriam os dados vivos.
- Ela processa em fluxo, página por página ou quadro por quadro, quando o formato permite, em vez de carregar o documento inteiro na memória.
- Ela limita a quantidade de pixels que aceita, que é também o que impede um arquivo pequeno, mas que se expande em um canvas gigantesco, de derrubar a aba.
O que fazer quando uma tarefa falha
- Feche as outras abas. Elas disputam o mesmo orçamento, e os navegadores não o dividem de forma justa.
- Processe menos arquivos de cada vez. Uma fila de um é mais lenta e tem muito mais chance de terminar.
- Reduza as dimensões primeiro. Cortar o lado maior pela metade deixa o consumo de memória em um quarto — e muitas vezes é o que você queria mesmo.
- Divida um PDF grande e processe as partes.
- Passe para um computador de mesa nas tarefas maiores. Isso não é uma falha do processamento local; é o uso correto do hardware que você tem.
- Reinicie o navegador se uma aba está aberta há dias. Abas de vida longa acumulam memória que um recarregamento libera.
O limite de qualquer estimativa
Os navegadores expõem apenas uma indicação grosseira da memória disponível, e alguns não expõem nada. Qualquer número que uma ferramenta local mostre é, portanto, uma estimativa construída a partir das dimensões do próprio arquivo e de um modelo conservador do pipeline, não uma leitura do sistema operacional. Serve para decidir se vale a pena tentar. Não é uma promessa de que a tarefa vai terminar, porque o fator decisivo — o que o resto do aparelho vai fazer nos próximos trinta segundos — é algo que uma página da web não consegue ver.
Ferramentas para isso
Fontes
- W3C — WebAssembly Core Specification, memory model
- W3C — Device Memory API, and why the value is coarse
- WHATWG — HTML Standard, transferable objects