One gave an idea,
But none had written the code.
Here, Hear, Here it is.
SProfile.rb
----------------8<--------------dñÄoupez-ici--------------8<----------------
# Statistical Time-Consumption Profiler
# An alternative to Ruby's profile.rb
# does not use set_trace_func().
# approximates the real thing by taking stack snapshots.
# possibly more accurate
# (profile.rb widens the C/Ruby speed gap while measuring)
class CallStats
CallStatsEntry = Struct.new(:method,:time,:time_nest)
def initialize
@table = {}
end
def eat_stack(stack)
stack.each_with_index {|frame,i|
next if i==0
method = File.basename(frame[0..frame.index(?:)])
pos = frame.rindex(?`)
method << frame[pos+1..-2] if pos
e = (@table[method] ||= CallStatsEntry.new(method,0,0))
e.time += 1 if i==1
e.time_nest += 1
}
end
def print_top_methods_to(stream)
column = :time_nest
#column = :time
ks = @table.keys.sort {|a,b|
@table[b].send(column) <=> @table[a].send(column)
}
i=0
ks.each {|k|
v = @table[k]
stream.printf "%40s %7d %7d\n", v.method, v.time, v.time_nest
i+=1
break if i>=32
}
end
end
foo = CallStats.new
foo.eat_stack proc{caller}.call
parent = $$
m=0
trap(12) {
if m<1; m+=1; foo.eat_stack caller; m-=1; end
}
fork {|pid|
while true; Process.kill 12,parent; sleep .01; end
}
END {
STDERR.puts; foo.print_top_methods_to(STDERR)
}
----------------8<--------------dñÄoupez-ici--------------8<----------------
matju