Une CLI pour analyser les décharges de tas de rubis. Merci à Sam Saffron pour l'idée et le code initial.
Ajoutez cette ligne à Gemfile de votre application:
gem 'heapy'
Puis exécuter:
$ bundle
Ou installez-le vous-même comme:
$ gem install heapy
Exécutez avec deux entrées pour produire les valeurs d'aujourd'hui.Dump qui ne sont pas présents dans Hier.Dump
$ heapy diff tmp/yesterday.dump tmp/today_morning.dump
Allocated STRING 9991 objects of size 399640/491264 (in bytes) at: scratch.rb:24
Exécutez avec trois entrées pour montrer le diff entre les deux premiers, mais seulement si les objets sont toujours conservés dans le troisième
$ 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
# ...
Passer le nom d'un fichier de sortie et des objets présents dans aujourd'hui.dump qui ne sont pas dans hier.Dump sera écrit dans ce fichier
$ 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
En raison de la façon dont le collecteur des ordures dans l'IRM gère les objets sur le tas de rubis, heapy diff
peut produire des difficultés incomplètes ou incorrectes dans les circonstances suivantes:
GC.compact
ou avec une compaction automatique activée, Heapy ne peut pas produire de difficultés, car les objets peuvent se déplacer dans différents emplacements de tas et apparaîtront comme nouvellement alloués même s'ils ne l'ont pas été. En général, tout mécanisme qui déplace les objets existants d'un emplacement de tas à un autre invalidera les rapports Diff. Éteignez toujours le compactage avant de prendre le décharge de tas <after>
.<after>
vidage si Ruby les allouait dans des emplacements de tas qui étaient précédemment occupés par différents objets dans le <before>
Dump, et qui ont ensuite été traités entre les deux décharges. Pour minimiser les chances que cela se produise, le déclenchement d'un GC majeur trois fois ou plus entre les décharges de tas peut aider les survivants en tir et ainsi stabiliser le tas avant de prendre un diff.Étape 1) Générez un vidage de tas. Vous pouvez le faire manuellement. Ou vous pouvez utiliser un outil comme déraillé_benchmarks
Étape 2) Une fois que vous avez le vidage de tas, vous pouvez l'analyser en utilisant cette 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
# ...
Remarque: La raison pour laquelle vous obtenez une génération "nil" est que ces objets ont été chargés de mémoire avant que votre code ne commence à suivre les allocations. Pour vous assurer que toutes les allocations sont suivies, vous pouvez exécuter votre script Ruby cette astuce. Créez d'abord un fichier trace.rb
qui ne commence que le traçage d'allocation:
# trace.rb
require 'objspace'
ObjectSpace.trace_object_allocations_start
Assurez-vous maintenant que cette commande est chargée avant d'exécuter votre script, vous pouvez utiliser Ruby's -I
pour spécifier un chemin de chargement et -r
pour spécifier une bibliothèque pour exiger, dans ce cas, notre fichier de trace
$ ruby -I ./ -r trace script_name.rb
Si la dernière ligne de votre fichier est invalide JSON, assurez-vous que vous fermez le fichier après avoir écrit le vidage Ruby Heap.
Vous pouvez explorer une génération spécifique. Dans l'exemple précédent, la 17e génération semble étrangement grande, vous pouvez y percer:
$ 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
Vous pouvez limiter la sortie en transmettant une valeur --lines
:
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump 17 --lines=6
Remarque: la valeur des lignes par défaut est de 50
Si vous souhaitez lire toutes les générations, vous pouvez utiliser la directive "All"
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump all
Vous pouvez également utiliser un analyseur de tas basé sur JS en ligne de T-LO pour les visualisations. Un autre outil est Harb
Après avoir vérifié le dépôt, exécutez $ bundle install
pour installer les dépendances. Ensuite, exécutez rake spec
pour exécuter les tests.
Pour installer ce gemme sur votre machine locale, exécutez bundle exec rake install
. Pour publier une nouvelle version, mettez à jour le numéro de version dans version.rb
, puis exécutez bundle exec rake release
, qui créera une balise GIT pour la version, pousse Git Commits and Tags, et poussez le fichier .gem
sur RubyGems.org.
Les rapports de bogues et les demandes de traction sont les bienvenus sur GitHub à https://github.com/schneems/heapy. Ce projet est destiné à être un espace sûr et accueillant pour la collaboration, et les contributeurs devraient adhérer au Code de conduite de l'alliance des contributeurs.
Le GEM est disponible en open source en vertu des termes de la licence MIT.