Límites de memoria del navegador al procesar archivos
Mi archivo solo pesa 15 MB. ¿Por qué se ha quedado la pestaña sin memoria?
El archivo del disco es la versión comprimida
Este es todo el malentendido en una frase: el número que ves en el gestor de archivos es el tamaño de los datos comprimidos, y no se puede procesar nada mientras está comprimido. Para redimensionar, recomprimir, convertir o analizar una imagen hay que decodificarla antes a píxeles en bruto, y los píxeles en bruto son enormes.
La aritmética es sencilla. Un píxel en memoria ocupa normalmente cuatro bytes: rojo, verde, azul y alfa. Una fotografía de 4000 × 3000 son doce millones de píxeles, así que el mapa de bits decodificado ocupa unos 48 MB. El JPEG del que salió podía pesar 4 MB. El archivo ha crecido doce veces antes de que empezara ningún trabajo.
| Dimensiones | Píxeles | Mapa de bits decodificado |
|---|---|---|
| 1920 × 1080 | 2,1 millones | unos 8 MB |
| 4000 × 3000 | 12 millones | unos 48 MB |
| 6000 × 4000 | 24 millones | unos 96 MB |
| 10000 × 10000 | 100 millones | unos 400 MB |
Y con una copia nunca basta
Un proceso realista mantiene varias copias a la vez: los bytes comprimidos de entrada, el mapa de bits de origen decodificado, un mapa de bits de salida con las nuevas dimensiones, los búferes internos del codificador y el resultado comprimido. Una herramienta que además te muestra una vista previa mantiene otra más. Para la fotografía de 4000 × 3000 de antes, un pico de trabajo de doscientos o trescientos megabytes es de lo más normal, para un archivo que parecía de 4 MB.
La rasterización de PDF se comporta igual, página a página: una página A4 renderizada a 300 DPI son unos 2480 × 3508 píxeles, unos 35 MB una vez decodificada, y una herramienta que renderiza varias páginas a la vez multiplica esa cifra. El vídeo es peor todavía, porque un decodificador necesita tener varios fotogramas de referencia residentes al mismo tiempo.
Dónde están los techos de verdad
- El presupuesto de memoria de una pestaña lo fija el navegador, no el sitio, y es menor que la memoria instalada en la máquina. Además se encoge cuando otras pestañas están ocupadas.
- Los módulos de WebAssembly compilados para el modelo de memoria de 32 bits habitual pueden direccionar como mucho cuatro gibibytes, y los navegadores suelen permitir bastante menos por instancia.
- Cada búfer tiene su propia longitud máxima, muy por debajo de la memoria total que puede usar una página.
- Los sistemas operativos móviles terminan una pestaña que crece demasiado, sin avisar y sin ningún error que la página pueda capturar.
- La memoria de gráficos es una reserva aparte y más pequeña. Un canvas mayor que la dimensión máxima de la plataforma sencillamente falla, por mucha memoria del sistema que quede libre.
Ninguno de estos límites se publica como una cifra única que puedas consultar, porque dependen del navegador, de la versión, del dispositivo y de qué más se esté ejecutando. Esa es la dificultad de verdad: una herramienta no puede preguntar cuánta memoria le está permitido usar.
Por qué los móviles son el caso estricto
Los móviles tienen menos memoria física, no tienen memoria de intercambio en el sentido del escritorio y llevan un sistema operativo agresivo a la hora de reclamársela a los procesos en segundo plano. Una pestaña del navegador es un proceso en segundo plano en cuanto contestas un mensaje. Por eso los navegadores móviles manejan presupuestos más ajustados y descartan una pestaña antes, y ese descarte se te suele presentar como que la página se recarga y pierdes tu trabajo, no como un error.
La consecuencia práctica es que un trabajo que termina en un portátil puede ser imposible en un móvil con el mismo archivo. Eso no es un defecto de la herramienta. Es una frontera de hardware, y la respuesta honesta es decirlo antes de empezar en vez de fallar a medio camino.
Cómo se comporta una herramienta cuidadosa
- Estima la memoria de trabajo a partir de las dimensiones decodificadas antes de reservar nada, y rechaza un trabajo que claramente no va a caber.
- Procesa un archivo cada vez en un dispositivo limitado, en lugar de ejecutar un lote en paralelo.
- Transfiere los búferes entre la página y sus workers en vez de copiarlos, así que un archivo grande no existe dos veces.
- Libera cada resultado en cuanto queda escrito, y revoca las URL temporales que, si no, mantendrían vivos los datos.
- Trabaja en flujo, página a página o fotograma a fotograma, allí donde el formato lo permite, en lugar de cargar un documento entero en memoria.
- Pone un tope al número de píxeles que acepta, que es también lo que impide que un archivo pequeño que se expande hasta un canvas enorme se lleve la pestaña por delante.
Qué puedes hacer cuando un trabajo falla
- Cierra otras pestañas. Compiten por el mismo presupuesto, y los navegadores no lo reparten de forma justa.
- Procesa menos archivos a la vez. Una cola de uno es más lenta y tiene muchas más probabilidades de terminar.
- Reduce primero las dimensiones. Reducir a la mitad el lado más largo deja la memoria de trabajo en una cuarta parte, y además suele ser lo que querías de todos modos.
- Divide un PDF grande y procesa las partes.
- Pásate a una máquina de escritorio para los trabajos más grandes. Esto no es un fracaso del procesamiento local; es el uso correcto del hardware que tienes.
- Reinicia el navegador si una pestaña lleva días abierta. Las pestañas de larga vida acumulan memoria que una recarga libera.
El límite de cualquier estimación
Los navegadores solo exponen una pista aproximada sobre la memoria disponible, y algunos no exponen nada. Por eso, cualquier cifra que te muestre una herramienta local es una estimación construida a partir de las dimensiones del propio archivo y de un modelo conservador del proceso, no una lectura del sistema operativo. Sirve para decidir si merece la pena intentar un trabajo. No es una promesa de que el trabajo vaya a terminar, porque el factor decisivo —qué esté haciendo el resto del dispositivo en los próximos treinta segundos— es algo que una página web no puede ver.
Herramientas para esta tarea
Fuentes
- W3C — WebAssembly Core Specification, memory model
- W3C — Device Memory API, and why the value is coarse
- WHATWG — HTML Standard, transferable objects