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