sumo
0

Trabajando con ficheros pesados

OutOfMemoryException. No entréis en pánico, ninguna de vuestras aplicaciones ha fallado, no es una excepción real. Os será más familiar a los que esteis trabajando con lectura y escritura de ficheros pesados y la mayoría os preguntaréis “si tengo 8GB de RAM y estoy trabajando con un fichero de 500MB, ¿qué está pasando aquí?”. Pues para saber por qué obtenemos este tipo de excepciones, primero hay que entender cómo funciona la memoria RAM.

Pensemos un momento en una habitación vacía de 25 m2. Vamos a ir colocando muebles poco a poco: un sofá (3m2) delante del mueble de la tele (2m2) y junto a una lámpara de pie (0.5m2), luego una mesa de centro (2m2) y una cómoda silla reclinable a un lado (1.5m2)… En este punto, tendremos libres 16m2, pero ¿qué pasa si queremos colocar también una cama? Pues lo más probable es que, a pesar de tener todavía mucho espacio libre, la propia colocación de los muebles no nos lo permita. Este es un ejemplo muy rudimentario que explica cómo funciona la memoria RAM.

A medida que la RAM se va ocupando y vaciando, se van generando huecos entre las direcciones de memoria ocupadas. La suma de estos huecos conforma nuestra memoria libre y es aquí donde nuestra aplicación tendrá que alojar ese fichero de 500MB con el que estamos trabajando. El problema es que, la mayoría de las veces, no tendremos un hueco continuo de 500MB, por lo que colocar ese fichero se asemejaría a intentar colocar una cama en nuestro salón. Es un fenómeno que se conoce como fragmentación.

fragmentationdiagram

Existe además, otro problema al trabajar con ficheros grandes y es que, aunque consigamos encontrar un hueco de 500MB para alojar nuestro fichero ¿que pasará si nuestra aplicación tiene que trabajar con dos ficheros a la vez? ¿y si en lugar de dos son cien? No vamos a encontrar huecos para cien ficheros, eso seguro. Este problema lo tendremos siempre que creemos una aplicación web que es utilizada por muchos usuarios simultáneamente que necesitan subir o descargar ficheros de gran tamaño.

La solución es muy sencilla: utilizar un buffer. Si en lugar de almacenar todo el fichero en memoria, almacenamos temporalmente sólo una pequeña parte de él, conseguiremos no sólo trabajar a prueba de errores, sino también ocupar mucho menos espacio de nuestra RAM. Si creamos un buffer de 1MB y trabajamos con cien ficheros simultáneamente, sólo ocuparemos 100MB en total y, además, cien buffers de 1MB pueden ser alojados fácilmente en cualquiera de los huecos de nuestra memoria.

Basta de cháchara, pongámonos manos a la obra. Este fragmento de código está en C#, pero puede trasladarse a cualquier otro lenguaje, ya que lo importante es el procedimiento. Podéis descargaros la aplicación de ejemplo completa, para depurarla paso a paso o para lo que queráis, desde mi GitHub. En el ejemplo, se lee un fichero y se escribe en disco, pero realmente puede modificarse para hacer cualquier otra operación, simplemente cambiando la linea 16.

 

 

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *