2010-09-09 18:19:35 +00:00
|
|
|
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
|
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
|
|
#
|
|
|
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
|
|
|
|
|
|
# A script to help finding performance bottlenecks:
|
2010-10-08 16:01:37 +00:00
|
|
|
#
|
|
|
|
# $ ruby-prof myscript.rb
|
2010-09-09 18:19:35 +00:00
|
|
|
# => String#+ gets called 50k times and takes 30s
|
2010-10-08 16:01:37 +00:00
|
|
|
#
|
|
|
|
# $ LOGCALLER='String#+' ruby -r bottleneck myscript.rb
|
2010-09-09 18:19:35 +00:00
|
|
|
# => String#+ called 40k times from:
|
|
|
|
# stuff.rb:42 in Myclass#uglymethod from
|
|
|
|
# stuff.rb:32 in Myclass#initialize
|
2010-10-08 16:01:37 +00:00
|
|
|
#
|
2010-09-09 18:19:35 +00:00
|
|
|
# now you know what to rewrite
|
|
|
|
|
|
|
|
|
2010-10-08 16:01:37 +00:00
|
|
|
|
|
|
|
def log_caller(cls, meth, singleton=false, histlen=nil)
|
2013-08-30 21:28:33 +00:00
|
|
|
histlen ||= ENV.fetch('LOGCALLER_MAXHIST', 16).to_i
|
|
|
|
dec_meth = 'm_' + meth.to_s.gsub(/[^\w]/) { |c| c.unpack('H*')[0] }
|
|
|
|
malias = dec_meth + '_log_caller'
|
|
|
|
mcntr = '$' + dec_meth + '_counter'
|
|
|
|
eval <<EOS
|
2010-10-08 16:01:37 +00:00
|
|
|
|
|
|
|
#{cls.kind_of?(Class) ? 'class' : 'module'} #{cls}
|
|
|
|
#{'class << self' if singleton}
|
2010-09-09 18:19:35 +00:00
|
|
|
alias #{malias} #{meth}
|
2010-10-08 16:01:37 +00:00
|
|
|
|
2010-09-09 18:19:35 +00:00
|
|
|
def #{meth}(*a, &b)
|
2010-10-08 16:01:37 +00:00
|
|
|
#{mcntr}[caller[0, #{histlen}]] += 1
|
2010-09-09 18:19:35 +00:00
|
|
|
#{malias}(*a, &b)
|
|
|
|
end
|
2010-10-08 16:01:37 +00:00
|
|
|
|
|
|
|
#{'end' if singleton}
|
2010-09-09 18:19:35 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#{mcntr} = Hash.new(0)
|
2010-10-08 16:01:37 +00:00
|
|
|
|
|
|
|
at_exit {
|
2013-08-30 21:28:33 +00:00
|
|
|
total = #{mcntr}.inject(0) { |a, (k, v)| a+v }
|
|
|
|
puts "\#{total} callers of #{cls} #{meth}:"
|
|
|
|
#{mcntr}.sort_by { |k, v|
|
|
|
|
-v
|
|
|
|
}[0, 4].each { |k, v|
|
|
|
|
puts " \#{'%.2f%%' % (100.0*v/total)} - \#{v} times from", k, ''
|
|
|
|
}
|
2010-10-08 16:01:37 +00:00
|
|
|
}
|
|
|
|
|
2010-09-09 18:19:35 +00:00
|
|
|
EOS
|
|
|
|
|
|
|
|
end
|
2010-10-08 16:01:37 +00:00
|
|
|
|
|
|
|
ENV['LOGCALLER'].to_s.split(';').map { |lc|
|
2013-08-30 21:28:33 +00:00
|
|
|
next if not lc =~ /^(.*)([.#])(.*)$/
|
|
|
|
cls, sg, meth = $1, $2, $3.to_sym
|
|
|
|
sg = { '.' => true, '#' => false }[sg]
|
|
|
|
cls = cls.split('::').inject(::Object) { |o, cst| o.const_get(cst) }
|
|
|
|
log_caller(cls, meth, sg)
|
2010-10-08 16:01:37 +00:00
|
|
|
}
|