jemallocを読んでみる(その4)

注意!

今日は、jemallocのコードは全然出てきません。しかも、大部分は過去mixiで書いた日記の焼き直しです。

本題

arena_lockbalance_hardを解説しようと読み進めました。すると、この関数を解説するにはアリーナの構造を説明する必要があることに気づきました。競合状態を緩和するために新たにアリーナを追加する処理だからです。じゃあ、アリーナの構造を説明するなら図が必要じゃんということで、図を描いていたらめちゃめちゃ面倒で自分でもこんがらがってきました。
色々考えて、昔Rubyのオブジェクトのインスペクタを作ったのでこれを使おうと思い立ちました。

mixiの日記に去年の7月に書いた内容です。

        • ここから

Rubyは言語は優れていますが、開発環境は比較的貧弱(だと思う、良いものがあったらぜひ教えてください)です。そのため、複雑なデータ構造を調子にのって作って、そこがバグると大変苦労します。
せめて良いインスペクタがあるといいなと常々思っていたのですが、今日ふとデータ構造をGraphviz(http://www.graphviz.org/)で表示させるとどうだろうと思いました。そこで作ったのがmodule Inspectです。
こんな感じで使います。

サンプルプログラムはじめ

require 'inspect'

class A
 def initialize
  @foo = "ABC"
  @bar = 123
  @baz = nil
 end
end

class B
 def initialize
  @a = A.new
  @b = nil
 end
end

class C
 def initialize
  @a = A.new
  @b = B.new
  @c = nil
 end
end

Inspect::inspect(C.new)

サンプルプログラムおわり

こうすると、Graphvizに食わせるdotファイルが\tmp\foo.dotという名前で出来て、これをGraphvizに食わせるとこんな感じのグラフになります。

これはいいということで、昔複雑なデータ構造で苦労したプログラムにこれを入れてデータ構造を表示しようとしました。その結果、20万行のdotファイルが出来てGraphvizがハングってしまいました・・・。だめじゃん

inspect.rb

module Inspect
 def inspect(obj)
  @fp = File.open("\\tmp\\foo.dot", "w")
  @appear_objects = {}
  @appear_objects[obj.__id__] = true
  @fp.print "digraph G {\n"
  inspect_aux(obj)
  @fp.print "#{obj.__id__} [label=\"#{obj.class.name}\"]\n"
  @fp.print "}\n"
  @fp.close
 end

 def inspect_aux(obj)
  case obj
  when Array
   i = 0
   obj.each do |vobj|
    emit(obj, vobj)
    @fp.print "#{obj.__id__} -> #{vobj.__id__} [label=\"#{i}\"]\n"
    i += 1
   end
   
  when Hash
   obj.each do |key, vobj|
    emit(obj, vobj)
    @fp.print "#{obj.__id__} -> #{vobj.__id__}\n"
   end

  else
   obj.instance_variables.each do |vstr|
    vobj = obj.instance_variable_get(vstr)
    @fp.print "#{obj.__id__} -> #{vobj.__id__} [label=\"#{vstr}\"]\n"
    emit(obj, vobj)
   end
  end
 end

 def emit(pobj, vobj)
  @fp.print "#{vobj.__id__} [label=\"#{vobj.class.name}\"]\n"
  if @appear_objects[vobj.__id__] != true then
   @appear_objects[vobj.__id__] = true
   inspect_aux(vobj)
  end
 end

 module_function(:inspect)
 module_function(:inspect_aux)
 module_function(:emit)
end 
          • 日記はここまで

これを使ってアリーナの構造体をRubyで書き直して自動的にグラフを書いてもらおうと考えています。

こんな感じです。

require 'inspect'

# jemallocの構造をrubyで表す
class Pthread_mutex_t
  def initialize
  end
end

class Arena_chunk_tree_t
  def initialize
    @rph_root = Arena_chunk_t.new(nil, Arena_chunk_t.new(nil, nil))
  end
end

class Arena_chunk_t
  def initialize(left, right)
    @rbe_left = left
    @rbe_left = right
    @map = []
  end
end

class Arena_bin_t
  def initialize
  end
end

class Arena_s
  def initialize
    @lock = Pthread_mutex_t.new
    @chunks = Arena_chunk_tree_t.new
    @bins = [Arena_bin_t.new, Arena_bin_t.new, nil]
  end
end

Inspect::inspect(Arena_s.new)

これで、こんな感じの図が出来ます。

言うまでもなく、これは構造のほんの一部なんですがこの方法でも大丈夫なんだろうか・・・。

たぶん、つづく・・・