Skip to content

Instantly share code, notes, and snippets.

@nurse nurse/yarv-profile.rb
Last active Jul 9, 2016

Embed
What would you like to do?
Profile perf(3)'s report into YARV instructions
#!/usr/bin/env ruby
require 'pp'
files = {'vm.inc' => [], 'insns.def' => []}
current_insn = nil
current_filename = 'vm.inc'
lineno_offset = 0
IO.foreach('vm.inc') do |line|
case line
when /^INSN_ENTRY\((\w+)\)/
files[current_filename] << $. - lineno_offset
current_insn = $1
files[current_filename] << current_insn
when /#line (\d+) "([^"]+)"/
current_filename = $2
lineno_offset = $. - $1.to_i
files[current_filename] << $. - lineno_offset
files[current_filename] << current_insn
end
end
def find_insn(files, fn, lineno)
ary = files[fn]
return nil unless ary
current = nil
ary.each_slice(2) do |n, insn|
return current || insn if lineno < n
current = insn
end
end
addrs = {}
s = `perf annotate -svm_exec_core --stdio --no-source`
s.scan(/^ *(?=[.0]*[1-9])([ .0-9]*) :\s*(\h+)/) do |pct, addr|
h = (addrs[addr.hex] ||= {})
h[:pct] = pct.to_f
end
/\A0*(\h+)[ .a-z]*\t0*(\h+)/i =~ `objdump -t miniruby|grep vm_exec_core`
#puts"0x#{$1}..#{"%#x"%[$1.hex+$2.hex]}"
from = $1.hex
to = from + $2.hex
`readelf --debug-dump=decodedline miniruby`.
scan(/^([a-z_.]+)\s+(\d+)\s+0x(\h+)/) do |fn, no, a|
addr = a.hex
next if addr < from
break if addr > to
lineno = no.to_i
h = (addrs[addr] ||= {})
h[:filename] = fn
h[:lineno] = lineno
insn = find_insn(files, fn, lineno)
h[:insn] = insn if insn
end
pcts = {}
current = ""
addrs.each_pair do |addr, h|
insn = h[:insn]
current = insn if insn
next unless pct = h[:pct]
pcts[current] ||= 0.0
pcts[current] += pct
end
pcts.sort_by(&:last).reverse_each do |key, pct|
puts "%20s: %5.2f" % [key, pct]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.