A Day in the Life

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分ぐらいがんばったけど俺の力じゃ無理だった。

記事の一覧 >