Tengo un programa que exhibe el comportamiento de una fuga de memoria. Gradualmente ocupa toda la memoria del sistema hasta que llena todo el espacio de intercambio y luego el sistema operativo lo elimina. Esto sucede una vez cada varios días.
He perfilado extensamente el montón de varias maneras (-hy, -hm, -hc) y he intentado limitar el tamaño del montón (-M128M) ajustado el número de generaciones (-G1) pero no importa lo que haga, el tamaño del montón parece constante -ish y bajo siempre (medido en kB, no en MB o GB). Sin embargo, cuando observo el programa en htop, su memoria residente aumenta constantemente.
Lo que esto me indica es que la fuga de memoria proviene de algún lugar además del montón de GHC. Mi programa utiliza dependencias, específicamente la biblioteca yaml de Haskell que envuelve la biblioteca C libyaml , es posible que la fuga esté en la cantidad de punteros externos que tiene para los objetos asignados por libyaml .
Mi pregunta es triple:
Esto ciertamente suena como que los punteros extranjeros no se están finalizando correctamente. Hay varias razones posibles para esto:
ForeignPtr no se liberan. Creo que en realidad hay una posibilidad decente de que sea la opción 3. Si el RTS constantemente encuentra suficiente memoria en la primera generación de GC, entonces simplemente no se molestará en ejecutar una colección importante. Afortunadamente, este es el más fácil de diagnosticar. Simplemente haga que su programa ejecute System.Memory.performGC de vez en cuando. Si eso lo soluciona, ha encontrado el error y puede modificar la frecuencia con la que desea hacerlo.
Otro posible problema es que podría tener punteros extraños en thunks de larga duración u otros cierres. Asegúrate de no hacerlo.
Una posibilidad particularmente fuerte cuando se trabaja con una biblioteca C envuelta es que las funciones de envoltorio devolverán ByteString s cuyas matrices subyacentes fueron asignadas por código C. Por lo tanto, cualquier ByteString que obtenga de yaml podría estar fuera del montón.