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)
これで、こんな感じの図が出来ます。
言うまでもなく、これは構造のほんの一部なんですがこの方法でも大丈夫なんだろうか・・・。
たぶん、つづく・・・