Upgrade to Pro — share decks privately, control downloads, hide ads and more …

YARVの最適化について調べた

na-o-ys
March 29, 2017

 YARVの最適化について調べた

社内勉強会

na-o-ys

March 29, 2017
Tweet

More Decks by na-o-ys

Other Decks in Programming

Transcript

  1. YARV ruby 1.8 Ҏલ ruby 1.9 Ҏ߱ VM όΠτίʔυ (ਤࢀߟ)

    Rubyͷ͘͠Έ -Ruby Under a Microscope - Pat Shaughnessy
  2. YARV ͸଎͍ • ϝϞϦޮ཰ • ϫʔΩϯάϝϞϦ͕ີʹͳΓΩϟογϡϛε͕ݮগ • όΠτίʔυ࠷దԽςΫχοΫ • ໋ྩྻ͕γϦΞϧʹฒͿͷͰૢ࡞͕खܰ

    • طଘݚڀͷ஌ݟ͕๛෋ (ࢀߟ) ·ͭ΋ͱ×࡫ాɺRuby 1.9ΛޠΔ - ˏIT http://www.atmarkit.co.jp/news/200712/25/ruby.html
  3. inline_const_cache ུ֓ (Πϝʔδ) module A::Module A_CONST = 'hello' end 10.times

    do ... puts A::Module::A_CONST ... end module A::Module A_CONST = 'hello' end 10.times do ... puts 'hello' ... end -> ϧʔϓ1ճ໨ ϧʔϓ2ճ໨Ҏ߱ ఆ਺୳ࡧ(஗͍)͕ॳճͷΈͰࡁΉ
  4. inline_const_cache όΠτίʔυ pry(main)> print RubyVM::InstructionSequence.compile("puts A_CONST").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000

    putself ( 1) 0001 getinlinecache 8, <is:0> 0004 getconstant :A_CONST 0006 setinlinecache <is:0> 0008 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0011 leave pry(main)> print RubyVM::InstructionSequence.compile("puts A_CONST").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000 putself ( 1) 0001 putnil 0002 getconstant :A_CONST 0004 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0007 leave ద༻લ ద༻ޙ
  5. inline_const_cache ιʔείʔυ pry(main)> print RubyVM::InstructionSequence.compile("puts A_CONST").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000

    putself ( 1) 0001 getinlinecache 8, <is:0> 0004 getconstant :A_CONST 0006 setinlinecache <is:0> 0008 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0011 leave • getinlinecache (8, <is:0>) • ΠϯϥΠϯΩϟογϡ <is:0> ʹ༗ޮͳ஋͕ηοτ͞Ε͍ͯΕ͹, ஋ΛελοΫʹੵΈ,
 8όΠτ໨ʹδϟϯϓ͢Δ • setinlinecache (<is:0>) • ΠϯϥΠϯΩϟογϡ <is:0> ʹελοΫτοϓͷ஋Ληοτ͢Δ https://github.com/ruby/ruby/blob/trunk/insns.def#L1182
  6. inline_const_cache
 Ωϟογϡফڈ • ruby ͷఆ਺͸࠶ఆٛՄೳ • ద੾ʹΩϟογϡফڈ͢Δඞཁ͕͋Δ • GLOBAL_CONSTANT_STATE •

    VMͰҰҙͳ஋ • ఆ਺ఆٛ/มߋͳͲͰ஋͕ΠϯΫϦϝϯτ • Ωϟογϡηοτ࣌ͷ஋ͱݱࡏͷ஋͕ҟͳΕ͹, ແޮΩϟογϡͱ Έͳ͞ΕΔ
  7. specialized_instruction
 ུ֓ (Πϝʔδ) puts 3 + 5 # 3.+(5) Fixnum#+

    puts 3.2 - 5.1 # (3.2).-(5.1) Float#- puts opt_plus(3, 5) puts opt_minus(3.2, 5.1) -> • جຊతͳԋࢉΛ࠷దԽ (ಛघԽ) • + ԋࢉ͸਺஋ʹରͯ͠ݺ͹ΕΔ͜ͱ͕ଟ͍ • ϝιου୳ࡧίετΛ࡟ݮ
  8. specialized_instruction
 όΠτίʔυ pry(main)> print RubyVM::InstructionSequence.compile("puts 3+5").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000

    putself ( 1) 0001 putobject 3 0003 putobject 5 0005 send <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>, nil 0009 send <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>, nil 0013 leave pry(main)> print RubyVM::InstructionSequence.compile("puts 3+5").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000 putself ( 1) 0001 putobject 3 0003 putobject 5 0005 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache> 0008 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0011 leave ద༻લ ద༻ޙ
  9. specialized_instruction
 ιʔείʔυ (໋ྩ) if (recv と val は Fixnum?) {

    if (Fixnum#+ は再定義されていない?) { return fix_plus(recv, val); } } else if (recv と val は Float?) { if (Float#+ は再定義されていない?) { return float_plus(recv, val); } } return send(:+, recv, val); (ུ֓) (ࢀߟ) YARV Maniacs ʲୈ 9 ճʳ ಛԽ໋ྩ http://magazine.rubyist.net/?0017-YarvManiacs https://github.com/ruby/ruby/blob/trunk/insns.def#L1309
  10. specialized_instruction
 ιʔείʔυ (ίϯύΠϧ) • όΠτίʔυ΁ͷίϯύΠϧ࣌ʹಛघԽ໋ྩʹஔ͖׵͍͑ͯΔ • + - * /

    % == != < >, … https://github.com/ruby/ruby/blob/trunk/compile.c#L2279 case idPLUS: SP_INSN(plus); return COMPILE_OK; case idMINUS: SP_INSN(minus); return COMPILE_OK; case idMULT: SP_INSN(mult); return COMPILE_OK; case idDIV: SP_INSN(div); return COMPILE_OK; case idMOD: SP_INSN(mod); return COMPILE_OK; case idEq: SP_INSN(eq); return COMPILE_OK; case idNeq: SP_INSN(neq); return COMPILE_OK; case idLT: SP_INSN(lt); return COMPILE_OK; case idLE: SP_INSN(le); return COMPILE_OK; case idGT: SP_INSN(gt); return COMPILE_OK; case idGE: SP_INSN(ge); return COMPILE_OK; case idLTLT: SP_INSN(ltlt); return COMPILE_OK; case idAREF: SP_INSN(aref); return COMPILE_OK;
  11. specialized_instruction ϝιου࠶ఆٛ • ࠷దԽର৅ͷΫϥε/ϝιουʹ͍ͭͯ, ࠶ఆٛͷ༗ແΛ ϑϥάͰ؅ཧ͍ͯ͠Δ˞ • Fixnum, Float, String,

    Array, Hash, BigNum, Symbol, Time, Regex, Nil, True, False • ϓϦϛςΟϒͳΫϥεʹର͢Δϝιου࠶ఆٛ͸,
 ύϑΥʔϚϯεμ΢ϯͷݪҼʹ΋ͳΔ ※ https://github.com/ruby/ruby/blob/trunk/vm_core.h#L565
  12. peephole_optimization jump LABEL1 ... LABEL1: jump LABEL2 jump LABEL2 ...

    -> ద༻લ ద༻ޙ • όΠτίʔυྻʹର͢Δෳ਺ͷ࠷దԽͷ૯শ • ෆཁͳδϟϯϓΛ࡟আͨ͠Γ
  13. operands_unification • සൟʹ࢖ΘΕΔ YARV ໋ྩͷΦϖϥϯυΛಛघԽ pry(main)> print RubyVM::InstructionSequence.compile("puts 1").disasm ==

    disasm: #<ISeq:<compiled>@<compiled>>================================ 0000 putself ( 1) 0001 putobject 1 0003 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0006 leave pry(main)> print RubyVM::InstructionSequence.compile("puts 1").disasm == disasm: #<ISeq:<compiled>@<compiled>>================================ 0000 putself ( 1) 0001 putobject_OP_INT2FIX_O_1_C_ 0002 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0005 leave ద༻લ ద༻ޙ
  14. ࠷దԽ YARV ·ͱΊ • όΠτίʔυԽͷԸܙ • ෳ਺ͷ࠷దԽख๏ • ࠓ೔঺հͨ͠Ҏ֎ʹ΋ •

    ϝιουσΟεύονͰͷΩϟογϡ౳ • ͜Ε͔ΒͷτϐοΫ • AOT/JIT • ʹඋ͑ͯ YARV ͷಈ͖͸཈͓͖͍͑ͯͨ