ルビーヒープダンプを分析するためのCLI。アイデアと初期コードについては、Sam Saffronに感謝します。
この行をアプリケーションのGemfileに追加します。
gem 'heapy'そして実行してください:
$ bundle
または、自分でインストールします:
$ gem install heapy
2つの入力で実行して、昨日に存在しない今日の値を出力します。
$ heapy diff tmp/yesterday.dump tmp/today_morning.dump
Allocated STRING 9991 objects of size 399640/491264 (in bytes) at: scratch.rb:24
3つの入力で実行して、最初の2つの間にdiffを表示しますが、3番目のオブジェクトがまだ保持されている場合のみです
$ 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
# ...
出力ファイルと今日のオブジェクトの名前を渡します。
$ 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
MRIのゴミコレクターがRuby Heapでオブジェクトを管理する方法により、 heapy diff次の状況では不完全または誤ったDIFFを生成する可能性があります。
GC.compact介して手動でRuby Heapを圧縮する場合、または自動コンピュータクションが有効になっている場合、Heapyは正確なDiffを生成できません。これは、オブジェクトが異なるヒープスロットに移動し、そうでなくても新しく割り当てられているように表示されるためです。一般に、既存のオブジェクトをあるヒープスロットから別のオブジェクトに移動するメカニズムは、DIFFレポートを無効にします。 <after>ヒープダンプを取る前に、常に圧縮をオフにしてください。<before>ダンプの異なるオブジェクトで占められていて、両方のダンプ間で扱われたヒープスロットにそれらを割り当てた場合、 <after>ダンプからオブジェクトを省略する可能性があります。これが起こる可能性を最小限に抑えるために、主要なGCをヒープダンプ間で3回以上トリガーすると、生存者の居住を支援し、DIFFを取得する前にヒープを安定させることができます。ステップ1)ヒープダンプを生成します。これを手動で行うことができます。または、Derailed_benchmarksなどのツールを使用できます
ステップ2)ヒープダンプを取得したら、この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
# ...
注:「nil」生成を取得する可能性がある理由は、コードが割り当ての追跡を開始する前に、これらのオブジェクトがメモリにロードされたためです。すべての割り当てを確実に追跡するために、このトリックをRubyスクリプトを実行できます。最初に、割り当てトレースのみを開始するファイルtrace.rbを作成します。
# trace.rb
require 'objspace'
ObjectSpace.trace_object_allocations_start
スクリプトを実行する前にこのコマンドがロードされていることを確認してください。Ruby's -I使用してロードパスと-r指定して、必要なライブラリを指定できます。
$ ruby -I ./ -r trace script_name.rb
ファイルの最後の行が無効なJSONの場合は、Ruby Heap Dumpを書き留めた後にファイルを閉じていることを確認してください。
特定の世代にドリルダウンできます。前の例では、17'th世代は奇妙に大きく見えます。
$ 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
--lines値を渡すことにより、出力を制限できます。
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump 17 --lines=6
注:デフォルトの行の値は50です
すべての世代を読みたい場合は、「すべて」指令を使用できます
$ heapy read tmp/2015-10-01T10:18:59-05:00-heap.dump all
T-LoのオンラインJSベースのHeap Analyzerを使用して、視覚化することもできます。別のツールはハーブです
リポジトリをチェックアウトした後、 $ bundle install実行して依存関係をインストールします。次に、 rake spec実行してテストを実行します。
この宝石をローカルマシンにインストールするには、 bundle exec rake install実行します。新しいバージョンをリリースするには、 version.rbのバージョン番号を更新してから、バージョンのgitタグを作成し、gitコミットとタグをプッシュし、 .gemファイルbundle exec rake release Rubygems.orgにプッシュします。
バグレポートとプルリクエストは、https://github.com/schneems/heapyのGithubで大歓迎です。このプロジェクトは、コラボレーションのための安全で居心地の良いスペースであることを目的としており、貢献者は貢献者の契約行動規範を遵守することが期待されています。
宝石は、MITライセンスの条件の下でオープンソースとして利用できます。