Fugas de espacio en Haskell
functional-programming lazy-evaluation (2)
He leído muchas veces que la evaluación perezosa en Haskell a veces puede llevar a fugas de espacio. ¿Qué tipo de código puede conducir a fugas de espacio? ¿Cómo detectarlos? ¿Y qué precauciones pueden tomarse de parte de un programador para evitarlas?
Me he encontrado con este problema cuando hago recursión sobre grandes estructuras de datos. Los acumulados acumulados llegan a ser demasiado y luego se produce una fuga de espacio.
En Haskell, debe estar constantemente al tanto de la posibilidad de encontrarse con una fuga de espacio. Como la iteración no existe, básicamente cualquier función recursiva tiene el potencial de generar una fuga de espacio.
Para evitar este problema, memorice las funciones recursivas, o vuelva a escribirlas de forma recursiva.
Probablemente obtendrás muchas respuestas, esta es la que he encontrado al intentar hacer alguna aplicación "del mundo real". Estaba usando subprocesos múltiples y algunas MVars para pasar datos (MVar es algo así como la memoria compartida bloqueada). Mi patrón típico era:
a <- takeMVar mvar
putMVar mvar (a + 1)
Y luego, solo a veces, cuando sucedió una condición adecuada hice algo como:
a <- takeMVar mvar
when (a > 10) ....
El problema es que el contenido de mvar era esencialmente (0 + 1 + 1 + 1 + ...) ... lo cual fue bastante intenso para números como 100k ... Este tipo de problema era bastante generalizado en mi código; desafortunadamente para aplicaciones de subprocesamiento múltiple es muy fácil meterse en tales problemas.
Detectando ... lo que hice fue iniciar haskell en el modo que produce datos sobre el consumo de memoria, iniciar y detener diferentes hilos y ver si la huella de memoria es estable o no ...
Anotomía de una fuga de thunk (con instrucciones de cómo depurarla)
Un ejemplo: pérdida de memoria Thunk como resultado de la función de mapa