[R-es] R y la gestión de memoria

Carlos J. Gil Bellosta gilbellosta en gmail.com
Mie Ago 11 09:48:00 CEST 2010


Hola, ¿qué tal?

Gracias por la respuesta. No obstante:

El día 10 de agosto de 2010 12:18, Gregorio R. Serrano
<grserrano en ccee.ucm.es> escribió:
> 1) Cuando un argumento se pasa a una función, se copia en memoria, R pasa
> los argumentos por valor no por referencia.

Mi argumento es pequeño: un número. Y el número de llamadas a la
función es del orden de 300. Ml objeto grande se crea dentro de la
función (más, abajo).

> 2) Al manipular el objeto, extraer elementos, etc. fragmentas la memoria,
> usas bloques temporalmente, pero más pequeños, de manera que al volver a
> llamar a la función no se puede usar el mismo bloque para la copia del
> objeto principal (entradas, en tu caso).

El código C subyacente hará pues una serie de mallocs. Que haga los
que quiera. Pero de la función, una vez sale de ella, no guardo nada.
En algún momento (véase la respuesta al punto (3)) tendrán que hacerse
los frees necesarios para devolver la memoria al sistema operativo (o
reservarla dentro del proceso para su reutilización). Es decir, en el
administrador de tareas de Windows (en mi caso) debería ver un
decrecimiento en el uso de memoria cada vez que se invocase gc() (al
menos) y el gráfico de uso de memoria de la pestaña de rendimiento
debería tener forma de sierra.

> 3) No sé cuándo llama R al garbage collector, pero no es automático, de
> manera que no libera y compacta los bloques de memoria libre automáticamente
> al salir de la función.

Salta automáticamente cuando se excede el "trigger" (un cierto nivel
de uso de memoria) que aparece en la llamada a gc() (aunque también se
puede llamar a mano). De hecho, en mi sistema, este comportamiento es
evidente al ejecutar el código del siguiente ejemplo.

En mi sistema hago (que es una versión simplificada de mi problema):

foo <- function(x) {
    kk <- rnorm( 10000000 )
    x + mean( kk )
}
sapply( 1:10, foo )

y gc(), automáticamente, va liberando espacio (y observo un uso de
"perfil de sierra" de la memoria desde el SO). De hecho, lo devuelve
al sistema operativo.

Mi función es análoga (un número de entrada, otro de salida y un
objeto grande en medio) aunque, obviamente, más compleja. Pero en mi
caso, si no lo fuerzo explícitamente, R usa cada vez más memoria
mientras que en el ejemplo anterior el uso de memoria se mantiene
constante.

Ya sé que llamadas a gc() pueden o no pueden desencadenar "frees" (al
menos, no lo harán mientras haya punteros apuntando a las páginas de
memoria reservadas). Y que los "frees", si se producen, pueden o no
pueden devolver memoria al sistema operativo. Por eso mi pregunta, más
concretamente, es: ¿por dónde empezar para comprender qué es lo que
sucede internamente y por qué en unos casos sucede una cosa y en otros
otra? ¿Qué es necesario saber para poder gestionar la memoria con
criterio más que a través de cierta dosis de heurísitica y prueba y
error?

¿Alguna pista?

Un saludo,

Carlos J. Gil Bellosta



Más información sobre la lista de distribución R-help-es