Goteo de memoria en Rails

Tenemos varios procesos corriendo con Active Job que acaban saturando la memoria asignada a sus workers, asi que le estoy echando un vistazo al asunto del uso de memoria en Ruby.  Antes de sospechar de la garbage collection, conviene mirar si no tendremos más bien un sindrome de Diogenes funcionando en las llamadas a ActiveRecord.

Una primera medida es intentar no recoger lo que no necesitamos. Por ejemplo este post recomienda tirar de pluck. Y si se tercia de los cursores de postgresql.

Otra cosa que me resulta especialmente sospechosa es la tendencia que  tienen los enumerables a convertirse en array.  En la consola, un .each devuelve ese array a no ser que lo remates con un ;nil. Pero ¿no se creara igualmente? ¿Convendria matar esa salida via un .reject{true}), simplificarlo con un .map {… 0}, o cambiarla por un .find {… false}? En principio eso deberia garantizar una llamada al GC, ya que no tendriamos el objeto de Active Record referenciado en ningun lado. En la practica, no acaba de funcionar, y tampoco el ‘lazy’, que da una ganancia minima. En cambio, la recomendacion de usar “find_each” con tamaños de batch pequeños sí que consigue limitar el uso de memoria.

Una cosa que no acabo de entender es que aunque se ejecuten las major_gc, no se libera la memoria que ActiveRecord ha empleado a lo largo de todos sus recorridos. Ciertamente no se acumula continuamente, asi que se puede discutir si es o no es un leak. Yo creo que si que lo es, que el hecho de que AR pueda reutilizar ese espacio no significa que no lo este bloqueando permanentemente.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.