tutorial sesiones rails español ejemplos descargar ruby-on-rails ruby memory memory-leaks ruby-prof

ruby on rails - sesiones - ¿Cómo rastrear una pérdida de memoria en mi código Ruby?



ruby on rails tutorial pdf (4)

Considere la gema memory_profiler para usar con Ruby 2.1.

Pregunta

Estoy depurando una fuga de memoria en una tarea de rake. Quiero ver una pila de llamadas de:

  • Objetos vivos
  • ¿Qué objeto o línea originalmente asignó esos objetos?

¿Es esto posible con ruby-prof?

Si no, ¿qué herramienta debo usar?

Preparar

Gemas

Tarea de rastrillo

  • Importa un archivo CSV directamente en una base de datos MySql utilizando los objetos DATA LOAD INFILE y Active Record.

Lo que he intentado

He probado los modos

  • RubyProf :: ASIGNACIONES
  • RubyProf :: MEMORY

Todo lo que dice en la documentación es:

RubyProf :: ALLOCATIONS Los informes de asignación de objetos muestran cuántos objetos asigna cada método en un programa.

RubyProf :: MEMORY Los informes de uso de memoria muestran la cantidad de memoria que usa cada método en un programa.

Esto implica que ruby-prof solo informa sobre la asignación total de objetos, no solo los que están vivos.

Probé Ruby-Mass y Bloat Check, pero ninguno parece ser capaz de hacer lo que quiero. Ruby-Mass también se cuelga porque encuentra objetos FactoryGirl en la memoria por alguna razón ...


Hay una gema de Ruby-Mass , que proporciona una buena API sobre ObjectSpace.

Una de las formas de abordar el problema es verificar las referencias una vez que haya terminado con su objeto.

object = ... # more logic puts Mass.references(object)

Si hay al menos una referencia, el objeto no es basura y debe averiguar cómo descartar esa referencia. Por ejemplo:

object.instance_variable_set("@example", nil) # or ObjectSpace.each_object(Your::Object::Class::Name).each do |obj| obj.instance_variable_set("@example", nil) end


No encontré a Ruby-prof muy útil a la hora de localizar fugas de memoria, porque necesita un intérprete de Ruby parcheado. La asignación de objetos de seguimiento se ha vuelto más fácil en Ruby 2.1. Tal vez es la mejor opción para explorar esto usted mismo.

Recomiendo la publicación del blog Ruby 2.1: objspace.so por tmml, que es uno de los desarrolladores principales de Ruby. Básicamente puedes buscar mucha información al depurar tu aplicación:

ObjectSpace.each_object{ |o| ... } ObjectSpace.count_objects #=> {:TOTAL=>55298, :FREE=>10289, :T_OBJECT=>3371, ...} require ''objspace'' ObjectSpace.memsize_of(o) #=> 0 /* additional bytes allocated by object */ ObjectSpace.count_tdata_objects #=> {Encoding=>100, Time=>87, RubyVM::Env=>17, ...} ObjectSpace.count_nodes #=> {:NODE_SCOPE=>2, :NODE_BLOCK=>688, :NODE_IF=>9, ...} ObjectSpace.reachable_objects_from(o) #=> [referenced, objects, ...] ObjectSpace.reachable_objects_from_root #=> {"symbols"=>..., "global_tbl"=>...} /* in 2.1 */

Con Ruby 2.1 puede incluso comenzar a rastrear la asignación de objetos nuevos y reunir metadatos sobre cada nuevo objeto:

require ''objspace'' ObjectSpace.trace_object_allocations_start class MyApp def perform "foobar" end end o = MyApp.new.perform ObjectSpace.allocation_sourcefile(o) #=> "example.rb" ObjectSpace.allocation_sourceline(o) #=> 6 ObjectSpace.allocation_generation(o) #=> 1 ObjectSpace.allocation_class_path(o) #=> "MyApp" ObjectSpace.allocation_method_id(o) #=> :perform

Utiliza pry y pry-debugger y comienza a explorar el montón de memoria donde crees que probablemente crecerá, respectivamente, prueba diferentes segmentos en tu código. Antes de Ruby 2.1 siempre confié en ObjectSpace.count_objects y ObjectSpace.count_objects la diferencia del resultado, para ver si un tipo de objeto crece particularmente.

La recolección de elementos no utilizados funciona correctamente cuando el número de objetos que crecen se vuelve a probar en una cantidad mucho menor durante las iteraciones en lugar de seguir creciendo. El recolector de basura debe funcionar todo el tiempo de todos modos, puede tranquilizarse mirando las estadísticas del Recolector de basura.

Desde mi experiencia, esto es String o Symbol ( T_STRING ). Los símbolos antes de Ruby 2.2.0 no se recogieron como basura, así que asegúrese de que su CSV o partes de él no se conviertan en símbolos en el camino.

Si no se siente cómodo, intente ejecutar su código en la JVM con JRuby. Al menos el perfil de memoria es mucho mejor soportado con herramientas como VisualVM.