K.Sasada's Home Page

こめんとのついか

こめんとこめんと!

message

please add long comment :).

_18(Mon)

土曜日に大江戸Ruby会議03でモテナイ発表をしてきました。

@koichisasada: Ruby の GC の問題点と改善手法についての一考察, 大江戸Ruby会議03 (2013.3).

スライド資料はこちら:http://www.atdot.net/~ko1/activities/oedorubykaigi03_ko1_pub.pdf

いやー、発表時間が足りなくて、改善案の話まで至らなくて残念ダッタナー。


で、ここで bitmap marking なんだから bitmap 画像が簡単に出るよって話だったんですが、実は GC というかオブジェクト空間の可視化って、昔から割とスグに出来る話ではあったし、実際に何人もの人が作っています。

で、折角の機会だし、私もやってみようかなぁ、と思ったのが、あれを作ったきっかけではありました。


で、戦略なんですが、mark 終了時に bitmap を書き出す、みたいなことをやるわけで、データ構造さえわかれば、それを実行するだけです。今回はあまり考えず、gc.c にちょいちょい手を入れることで行いました。

で作った結果はこちら。

文字列がどわーっと増えて、赤くなっていく様はホラーです。

これらの例は、結構恣意的というか、パターン化された例なので、実際のアプリでどのような挙動を示すかは、見てみたいような気がしますね。


さて、画像データを出すのは、だから簡単なのです。出すだけなら職場から帰る途中の電車の中だけで出来た。

これを、画像ファイルに変換し、さらには動画までするのが面倒だった。

ベタ bitmap を画像編集ソフトや動画作成ソフトに渡すためには適切なファイルフォーマットに変換しないといけませんが、さてこれをどうやればよいか。

ということで、今回は rcairo を使って png ファイルをガンガン作成して、それを ffmpeg でくっつける、という方針をとりました。きっと、もっと効率的な方法もあったと思いますが、手持ちで触れそうなのがこれくらいだった。

ベタデータから png ファイルを作成するのがこっち。

require 'rubygems'
require 'cairo'
require 'pp'

require 'rubygems'
require 'cairo'
require 'pp'
DIR = '/home/ko1/src/tmp/gc'

pid_files = Hash.new{|h, k| h[k] = []}

Dir.glob("#{DIR}/gcbitmap*").sort.each{|file|
  if /gcbitmap-(\d+)-(\d+)-(\d+)x(\d+)/ =~ file
    f = {
      file: file,
      pid: $1.to_i,
      cnt: $2.to_i,
      y: $3.to_i,
      x: $4.to_i,
    }
    # p [file, x, y, File.size(file)]
    pid_files[f[:pid]] << f
  end
}

pid_files.each{|pid, files|
  next if files.size < 200
  max_x = files.max_by{|f| f[:x]}[:x]
  max_y = files.max_by{|f| f[:y]}[:y]
  p [pid, files.size, max_x, max_y]

  # next

  files.each{|f|
    x = f[:x]
    y = f[:y]
    file = f[:file]

    background_surface = Cairo::ImageSurface.new(max_x, max_y)
    surface = Cairo::ImageSurface.new(File.read(file), Cairo::Format::RGB24, x, y, x * 4)

    Cairo::Context.new(background_surface){|context|
      context.set_source_rgb(0.2, 0.2, 0.2) # blue
      context.rectangle(0, 0, max_x, max_y)
      context.fill
      context.set_source(surface)
      context.paint
    }


    dirname = "#{DIR}/png-#{pid}"
    Dir.mkdir(dirname) if !FileTest.directory?(dirname)
    png_filename = "#{dirname}/#{'%08d' % f[:cnt]}.png"
    p png_filename
    background_surface.write_to_png(png_filename)
  }
}

まぁ、画像処理っぽいことをしているのは、高さを合わせるために画像を弄った、というところくらいではあるのですが。

いやはや、楽しかったです。


んで、こういう作業をするには、前述の通り gc.c を弄れば簡単なんですが、そうじゃないとやりづらい。何がやりづらいかというと、mark 終了時にすぐにこれを起動することなわけです。ということで、何かしら、これを拡張ライブラリから叩けるようなものにしておきたいなぁ、という気がしているところです。


好きなだけ長いコメントをどうぞ。

お名前


back

tton 記述が使えます。YukiWikiな記述してりゃ問題ありません。

「行頭に#code」 と、「行頭に#end」 で挟むと、その間の行は pre で囲まれます。プログラムのソースを書くときに使ってください。

例:

#code

(なんかプログラム書く)

#end

リンクは

[[なまえ|http://www.example.org]]

とか

[[http://www.example.org]]

で貼れます。

$Date: 2003/04/28 10:27:51 $