2006-06-23
ruby-prof で部分的なプロファイリングをする
元の ruby-prof は -r unprof で起動時から実行が前提で at_exit で終了時にプロファイリングの結果を出力する。なので部分的にプロファイラーの結果を取得したいというときのために unprof.rb をちょっと変えてこんなのを書いてみた。
require 'prof'
case ENV["RUBY_PROF_CLOCK_MODE"]
when "gettimeofday"
  Prof.clock_mode = Prof::GETTIMEOFDAY
  $stderr.puts("use gettimeofday(2) for profiling") if $VERBOSE
when "cpu"
  if ENV.key?("RUBY_PROF_CPU_FREQUENCY")
    Prof.cpu_frequency = ENV["RUBY_PROF_CPU_FREQUENCY"].to_f
  else
    begin
      open("/proc/cpuinfo") do |f|
        f.each_line do |line|
          s = line.slice(/cpu MHz\s*:\s*(.*)/, 1)
          if s
            Prof.cpu_frequency = s.to_f * 1000000
            break
          end
        end
      end
    rescue Errno::ENOENT
    end
  end
  Prof.clock_mode = Prof::CPU
  $stderr.puts("use CPU clock counter for profiling") if $VERBOSE
else
  Prof.clock_mode = Prof::CLOCK
  $stderr.puts("use clock(3) for profiling") if $VERBOSE
end
module Prof
  def result
    str = ''
    result = Prof.stop
    total = result.detect { |i|
      i.method_class.nil? && i.method_id == :"#toplevel"
    }.total_time
    if total == 0.0
      total = 0.001
    end
    sum = 0
    str << "  %%   cumulative   self              self     total\n"
    str << " time   seconds   seconds    calls  ms/call  ms/call  name\n"
    for r in result
      sum += r.self_time
      if r.method_class.nil?
        name = r.method_id.to_s
      elsif r.method_class.is_a?(Class)
        name = r.method_class.to_s + "#" + r.method_id.to_s
      else
        name = r.method_class.to_s + "." + r.method_id.to_s
      end
      str << sprintf("%6.2f %8.3f  %8.3f %8d %8.2f %8.2f  %s\n",
                    r.self_time / total * 100, sum, r.self_time, r.count,
                    r.self_time * 1000 / r.count, r.total_time * 1000 / r.count,
                    name)
    end
    str
  end
  def profiler
    Prof.start
    yield
    Prof.result
  end
  module_function :result, :profiler
end
んで読み込んで
puts Prof.profiler {
  a = (1..100).to_a
  a.map{|i| i * i}.find_all{|i| i / 2 }
}
puts '-----'
puts Prof.profiler {
  a = (1..10000).to_a
  a.map{|i| i * i}.find_all{|i| i / 2 }
}
みたいに実行するとこんな結果を得ることができる。
%%   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
100.00    0.020     0.020        1    20.00    20.00  Array#map
  0.00    0.020     0.000      100     0.00     0.00  Fixnum#/
  0.00    0.020     0.000      100     0.00     0.00  Fixnum#*
  0.00    0.020     0.000        1     0.00    20.00  #toplevel
  0.00    0.020     0.000        1     0.00     0.00  Array#each
  0.00    0.020     0.000        1     0.00     0.00  Range#each
  0.00    0.020     0.000        1     0.00     0.00  Enumerable.to_a
  0.00    0.020     0.000        1     0.00     0.00  Enumerable.find_all
----
  %%   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 36.36    0.040     0.040        1    40.00    50.00  Array#each
 36.36    0.080     0.040        1    40.00    50.00  Array#map
  9.09    0.090     0.010    10000     0.00     0.00  Fixnum#*
  9.09    0.100     0.010    10000     0.00     0.00  Fixnum#/
  9.09    0.110     0.010        1    10.00    10.00  Range#each
  0.00    0.110     0.000        1     0.00   110.00  #toplevel
  0.00    0.110     0.000        1     0.00    50.00  Enumerable.find_all
  0.00    0.110     0.000        1     0.00    10.00  Enumerable.to_a
実家回線が落ちてる
サーバじゃなくていつも落ちるのは回線(ルータ)なんだよなぁ。FLET's 光付属ルータのうんこめ。
あとうちは tokuhirom のところとちがって妹メソッドが使えないのがツライです。
ruby-prof
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/25917
速ぇー。スバラシス。
svn co http://svn.shugo.net/src/ruby-prof/trunk/ ruby-prof
cd ruby-prof
ruby extconf.rb
make
sudo make install
で。実行は
ruby -runprof foo.rb
関係ないけど、前田さんはさわやかでかっこいい人でした。
追記
rubygems にあがってるじゃんすか!
ActiveRecode::Base.inherited を書き換えちゃうのか
http://idm.s9.xrea.com/ratio/2006/06/23/000471.html
なるほどー。svn head に入ってる、というのは AR::find の :conditions に hash を渡すことでそいつで where してくれる機能です。
E2v
range 対応してるじゃん!なので perl like な regexp 書いてから選択して
:'<,'>E2v
で変わる!!すばら C
Tシャツがない
ああゆりーかさんのようにユニクロのデザイナーズTシャツ1000円で投げ売りの時20種類かっとけば良かった!代官山なのでユニTとか来てる人居ないからかぶる心配ない!!!(
K林君
知り合いの K林君が、いままでは「アニオタとかキモイ全滅しろ!!!」「ラノベとかゴミ!!!」とか云っていたのに、ラノベ原作の憂鬱なアニメを見てから「憂鬱以外のアニメなんてゴミ!!!」とかいいつつ DVD 買ってるあたりあれだなー、と思った。
memo
vim で dRuby で E2v()
ActiveRecord を SQLObject っぽく
model 以下のモデルオブジェクトを作るタイミングで
module ::Kernel
  def User(options = {})
    ::User.find(:all, :conditions => options)
  end
end
とかいれてやると
User(:firstname => 'taro', :lastname => 'yamada')
User(3)
みたいにかけるなぁ(svn head)。Maiha が云ってたっけ。
自動生成させようとして5分ぐらいがんばったけど俺の力じゃ無理だった。