What are some common instruction sequences in Ruby?
results (172130552) instructions captured
==== top ====
opt_send_without_block = 26771616
getlocal_WC_0 = 24152570
leave = 20986069
putself = 13459785
getinstancevariable = 7888974
dup = 6825082
branchunless = 6586019
opt_getconstant_path = 5920847
setlocal_WC_0 = 5705813
putobject = 5508571
pop = 5093786
branchif = 5013099
getlocal_WC_1 = 3849367
send = 3826551
opt_aref = 3704390
putnil = 3367462
setinstancevariable = 2550503
nop = 2517919
invokesuper = 1327654
getblockparamproxy = 1262760
anytostring = 970513
objtostring = 970483
invokeblock = 929644
topn = 778921
opt_nil_p = 730179
==== 2 chains ====
chain ["putself", "opt_send_without_block"] = 7487855
chain ["leave", "leave"] = 7230372
chain ["getlocal_WC_0", "opt_send_without_block"] = 6637231
chain ["opt_send_without_block", "putself"] = 5202440
chain ["opt_send_without_block", "getlocal_WC_0"] = 3166332
chain ["putself", "getlocal_WC_0"] = 3079552
chain ["dup", "branchif"] = 3020450
chain ["opt_send_without_block", "getinstancevariable"] = 2921281
chain ["getlocal_WC_0", "getlocal_WC_0"] = 2513945
chain ["opt_send_without_block", "opt_send_without_block"] = 2194330
chain ["setlocal_WC_0", "getlocal_WC_0"] = 2104506
chain ["getinstancevariable", "getlocal_WC_0"] = 2079343
chain ["branchunless", "getlocal_WC_0"] = 2078492
chain ["opt_getconstant_path", "opt_send_without_block"] = 2069089
chain ["opt_send_without_block", "leave"] = 1997695
chain ["leave", "dup"] = 1970800
chain ["leave", "pop"] = 1960633
chain ["getlocal_WC_0", "leave"] = 1779102
chain ["opt_send_without_block", "opt_getconstant_path"] = 1751133
chain ["leave", "opt_send_without_block"] = 1675828
chain ["leave", "getlocal_WC_0"] = 1655517
chain ["opt_send_without_block", "branchunless"] = 1511248
chain ["branchunless", "putself"] = 1504074
chain ["getlocal_WC_0", "opt_aref"] = 1494720
chain ["opt_send_without_block", "setlocal_WC_0"] = 1492185
==== 3 chains ====
chain ["opt_send_without_block", "putself", "opt_send_without_block"] = 3413684
chain ["leave", "leave", "leave"] = 3349984
chain ["putself", "opt_send_without_block", "putself"] = 1545718
chain ["dup", "branchif", "leave"] = 1389588
chain ["getlocal_WC_0", "opt_send_without_block", "getlocal_WC_0"] = 1359823
chain ["putself", "getlocal_WC_0", "opt_send_without_block"] = 1318387
chain ["getinstancevariable", "dup", "branchif"] = 1253995
chain ["putself", "opt_send_without_block", "opt_send_without_block"] = 1187504
chain ["getlocal_WC_0", "opt_send_without_block", "putself"] = 1077235
chain ["branchunless", "putnil", "leave"] = 1055231
chain ["opt_send_without_block", "getlocal_WC_0", "opt_send_without_block"] = 1054997
chain ["getlocal_WC_0", "getlocal_WC_0", "opt_send_without_block"] = 1040941
chain ["opt_send_without_block", "putself", "getlocal_WC_0"] = 1032791
chain ["putself", "opt_send_without_block", "getinstancevariable"] = 1016305
chain ["branchunless", "getlocal_WC_0", "leave"] = 942084
chain ["getlocal_WC_0", "opt_aref", "leave"] = 924653
chain ["opt_send_without_block", "getinstancevariable", "dup"] = 916901
chain ["dup", "branchif", "pop"] = 912485
chain ["dup", "objtostring", "anytostring"] = 887359
chain ["opt_send_without_block", "opt_getconstant_path", "opt_send_without_block"] = 847526
chain ["putself", "getlocal_WC_0", "invokesuper"] = 817403
chain ["opt_aref", "opt_send_without_block", "putself"] = 797899
chain ["pop", "putself", "opt_send_without_block"] = 776257
chain ["topn", "opt_send_without_block", "branchif"] = 762999
chain ["putself", "opt_send_without_block", "getlocal_WC_0"] = 756618
==== 4 chains ====
chain ["leave", "leave", "leave", "leave"] = 1986709
chain ["putself", "opt_send_without_block", "putself", "opt_send_without_block"] = 1450282
chain ["getinstancevariable", "dup", "branchif", "leave"] = 925721
chain ["opt_send_without_block", "putself", "opt_send_without_block", "opt_send_without_block"] = 904834
chain ["opt_send_without_block", "getinstancevariable", "dup", "branchif"] = 881274
chain ["opt_send_without_block", "putself", "opt_send_without_block", "putself"] = 781554
chain ["getlocal_WC_0", "dup", "objtostring", "anytostring"] = 721364
chain ["putself", "getlocal_WC_0", "opt_send_without_block", "getlocal_WC_0"] = 669573
chain ["getlocal_WC_0", "opt_aref", "leave", "dup"] = 665421
chain ["leave", "dup", "setlocal_WC_0", "branchunless"] = 610493
chain ["getinstancevariable", "getlocal_WC_0", "opt_aref", "leave"] = 605809
chain ["dup", "objtostring", "anytostring", "putobject"] = 583694
chain ["putself", "opt_send_without_block", "getinstancevariable", "dup"] = 578240
chain ["putself", "opt_send_without_block", "getlocal_WC_0", "opt_send_without_block"] = 566360
chain ["opt_aref", "leave", "dup", "setlocal_WC_0"] = 560787
chain ["opt_send_without_block", "putself", "getlocal_WC_0", "invokesuper"] = 547972
chain ["putobject", "getlocal_WC_0", "dup", "objtostring"] = 525379
chain ["dup", "setlocal_WC_0", "branchunless", "getlocal_WC_0"] = 514989
chain ["opt_aref", "opt_send_without_block", "putself", "getlocal_WC_0"] = 510009
chain ["putself", "opt_send_without_block", "opt_send_without_block", "leave"] = 501988
chain ["setlocal_WC_0", "branchunless", "getlocal_WC_0", "leave"] = 498063
chain ["getlocal_WC_0", "opt_send_without_block", "putself", "opt_send_without_block"] = 478331
chain ["getlocal_WC_0", "setinstancevariable", "getlocal_WC_0", "setinstancevariable"] = 476456
chain ["putself", "getlocal_WC_0", "invokesuper", "getinstancevariable"] = 472142
chain ["invokesuper", "getinstancevariable", "getlocal_WC_0", "opt_aref"] = 472136
build Ruby with dtrace & set VM_COLLECT_USAGE_DETAILS
to 1
run activerecord tests and capture instruction events with this stap script
// ruby-instructions.stp
probe process("/home/adam/.rubies/ruby-master/bin/ruby").mark("insn")
{
printf("%s\n", user_string($arg1))
}
Capture with,
sudo stap ruby-instructions.stp -o rails-tests2.txt -x $(pgrep ruby)
Parse the output with this script:
# parse_stap.rb
counts = {}
two_chains = {}
three_chains = {}
four_chains = {}
last = []
File.new("activerecord.txt", "r").each do |line|
if !line.valid_encoding?
# reset history when we encounter an invalid line
last = []
next
end
instruction = line.strip
if counts[instruction]
counts[instruction] += 1
else
counts[instruction] = 1
end
if last.size == 3
key = last + [instruction]
if two_chains[key.last(2)]
two_chains[key.last(2)] += 1
else
two_chains[key.last(2)] = 1
end
if three_chains[key.last(3)]
three_chains[key.last(3)] += 1
else
three_chains[key.last(3)] = 1
end
if four_chains[key.last(4)]
four_chains[key.last(4)] += 1
else
four_chains[key.last(4)] = 1
end
last.shift
end
last.append(instruction)
end
puts counts.inspect
puts "="*100
puts "results (#{counts.values.sum}) instructions captured"
puts "\n==== top ====\n\n"
counts.sort_by { |x| x.last }.reverse.first(25).each do |(key, value)|
puts "#{key} = #{value}"
end
puts "\n==== 2 chains ====\n\n"
two_chains.sort_by { |x| x.last }.reverse.first(25).each do |(key, value)|
puts "chain #{key.inspect} = #{value}"
end
puts "\n==== 3 chains ====\n\n"
three_chains.sort_by { |x| x.last }.reverse.first(25).each do |(key, value)|
puts "chain #{key.inspect} = #{value}"
end
puts "\n==== 4 chains ====\n\n"
four_chains.sort_by { |x| x.last }.reverse.first(25).each do |(key, value)|
puts "chain #{key.inspect} = #{value}"
end