Una CLI para analizar los vertederos de montón de rubí. Gracias a Sam Saffron por la idea y el código inicial.
Agregue esta línea al archivo gem de su aplicación:
gem 'heapy'
Y luego ejecutar:
$ bundle
O instálelo usted mismo como:
$ gem install heapy
Ejecute con dos entradas para emitir los valores de hoy.dump que no están presentes en ayer.dump
$ heapy diff tmp/yesterday.dump tmp/today_morning.dump
Allocated STRING 9991 objects of size 399640/491264 (in bytes) at: scratch.rb:24
Ejecute con tres entradas para mostrar la diferencia entre los dos primeros, pero solo si los objetos aún se conservan en el tercero
$ heapy diff tmp/yesterday.dump tmp/today_morning.dump tmp/today_afternoon.dump
Retained STRING 9991 objects of size 399640/491264 (in bytes) at: scratch.rb:24
# ...
Pasar en el nombre de un archivo de salida y los objetos presentes en hoy.dump que no están en ayer. Dump se escribirá en ese archivo
$ heapy diff tmp/yesterday.dump tmp/today.dump --output_diff=output.json
Allocated STRING 9991 objects of size 399640/491264 (in bytes) at: scratch.rb:24
# ...
Writing heap dump diff to output.json
Debido a cómo el recolector de basura en MRI gestiona los objetos en el montón de rubí, heapy diff
puede producir diferencias incompletas o incorrectas en las siguientes circunstancias:
GC.compact
o con la compactación automática habilitada, Smisapy no puede producir diferencias precisas, porque los objetos pueden moverse a diferentes ranuras de montón y aparecerán como recién asignados incluso si no lo estaban. En general, cualquier mecanismo que mueva los objetos existentes de una ranura de montón a otro invalidará informes de diff. Siempre apague la compactación antes de tomar el volcado de montón <after>
.<after>
si Ruby los asignó a ranuras de montón que anteriormente estaban ocupadas por diferentes objetos en el volcado <before>
, y que luego se desacallaron entre ambos vertederos. Para minimizar la posibilidad de que esto suceda, desencadenar un GC importante tres o más veces entre los vertederos de montón puede ayudar a los sobrevivientes de la tenencia y, por lo tanto, estabilizar el montón antes de tomar una diferencia.Paso 1) Genere un volcado de montón. Podrías hacer esto manualmente. O puede usar una herramienta como Desariled_Benchmarks
Paso 2) Una vez que tenga el volcado de montón, puede analizarlo usando esta CLI:
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump
Generation: nil object count: 209191
Generation: 14 object count: 407
Generation: 15 object count: 638
Generation: 16 object count: 748
Generation: 17 object count: 1023
Generation: 18 object count: 805
# ...
Nota: La razón por la que puede estar obteniendo una generación "nulo" es que estos objetos se cargaron en la memoria antes de que su código comenzara a rastrear las asignaciones. Para garantizar que se rastreen todas las asignaciones, puede ejecutar su script de Ruby este truco. Primero cree un archivo trace.rb
que solo inicia el rastreo de asignación:
# trace.rb
require 'objspace'
ObjectSpace.trace_object_allocations_start
Ahora asegúrese de que este comando esté cargado antes de ejecutar su script, puede usar Ruby's -I
para especificar una ruta de carga y -r
para especificar una biblioteca para requerir, en este caso nuestro archivo de rastreo
$ ruby -I ./ -r trace script_name.rb
Si la última línea de su archivo no es válido JSON, asegúrese de que esté cerrando el archivo después de escribir el volcado de montón de rubí.
Puede profundizar en una generación específica. En el ejemplo anterior, la generación 17 'se ve extrañamente grande, puede perforarlo:
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump 17
Analyzing Heap (Generation: 17)
-------------------------------
allocated by memory (44061517) (in bytes)
==============================
39908512 /app/vendor/ruby-2.2.3/lib/ruby/2.2.0/timeout.rb:79
1284993 /app/vendor/ruby-2.2.3/lib/ruby/2.2.0/openssl/buffering.rb:182
201068 /app/vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:223
189272 /app/vendor/bundle/ruby/2.2.0/gems/newrelic_rpm-3.13.2.302/lib/new_relic/agent/stats_engine/stats_hash.rb:39
172531 /app/vendor/ruby-2.2.3/lib/ruby/2.2.0/net/http/header.rb:172
92200 /app/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.3/lib/active_support/core_ext/numeric/conversions.rb:131
Puede limitar la salida pasando en un valor --lines
:
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump 17 --lines=6
Nota: El valor de las líneas predeterminadas es 50
Si desea leer todas las generaciones, puede usar la Directiva "Todos"
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump all
También puede usar el analizador Heap basado en JS en línea de T-LO para visualizaciones. Otra herramienta es el puerto
Después de revisar el repositorio, ejecute $ bundle install
para instalar dependencias. Luego, ejecute rake spec
para ejecutar las pruebas.
Para instalar esta gema en su máquina local, ejecute bundle exec rake install
. Para lanzar una nueva versión, actualice el número de versión en version.rb
y luego ejecute bundle exec rake release
, que creará una etiqueta GIT para la versión, Push Git Commits and Tags, y empuje el archivo .gem
a rubygems.org.
Los informes de errores y las solicitudes de extracción son bienvenidas en GitHub en https://github.com/schneems/heapy. Este proyecto está destinado a ser un espacio seguro y acogedor para la colaboración, y se espera que los contribuyentes se adhieran al Código de Conducta del Pacto de contribuyente.
La gema está disponible como código abierto bajo los términos de la licencia MIT.