[ruby-cvs:73359] tenderlove:r66258 (trunk): Speed up hash literals by duping

tenderlove at ruby-lang.org tenderlove at ruby-lang.org
Fri Dec 7 03:28:22 JST 2018


tenderlove	2018-12-07 03:28:21 +0900 (Fri, 07 Dec 2018)

  New Revision: 66258

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66258

  Log:
    Speed up hash literals by duping
    
    This commit replaces the `newhashfromarray` instruction with a `duphash`
    instruction.  Instead of allocating a new hash from an array stored in
    the Instruction Sequences, store a hash directly in the instruction
    sequences and dup it on execution.
    
    == Instruction sequence changes ==
    
    ```ruby
    code = <<-eorby
      { "foo" => "bar", "baz" => "lol" }
    eorby
    
    insns = RubyVM::InstructionSequence.compile(code, __FILE__, nil, 0, frozen_string_literal: true)
    puts insns.disasm
    ```
    
    On Ruby 2.5:
    
    ```
    == disasm: #<ISeq:<compiled>@test.rb:0 (0,0)-(0,36)>====================
    0000 putobject        "foo"
    0002 putobject        "bar"
    0004 putobject        "baz"
    0006 putobject        "lol"
    0008 newhash          4
    0010 leave
    ```
    
    Ruby 2.6 at r66174 3b6321083a2e3525da3b34d08a0b68bac094bd7f:
    
    ```
    $ ./ruby test.rb
    == disasm: #<ISeq:<compiled>@test.rb:0 (0,0)-(0,36)> (catch: FALSE)
    0000 newhashfromarray             2, ["foo", "bar", "baz", "lol"]
    0003 leave
    ```
    
    Ruby 2.6 + This commit:
    
    ```
    $ ./ruby test.rb
    == disasm: #<ISeq:<compiled>@test.rb:0 (0,0)-(0,36)> (catch: FALSE)
    0000 duphash                      {"foo"=>"bar", "baz"=>"lol"}
    0002 leave
    ```
    
    == Benchmark Results ==
    
    Compared to 2.5.3:
    
    ```
    $ make benchmark ITEM=hash_literal_small COMPARE_RUBY=/Users/aaron/.rbenv/versions/2.5.3/bin/ruby
    generating known_errors.inc
    known_errors.inc unchanged
    ./revision.h unchanged
    /Users/aaron/.rbenv/shims/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver \
                --executables="compare-ruby::/Users/aaron/.rbenv/versions/2.5.3/bin/ruby -I.ext/common --disable-gem" \
                --executables="built-ruby::./miniruby -I./lib -I. -I.ext/common  -r./prelude --disable-gem" \
                $(find ./benchmark -maxdepth 1 -name '*hash_literal_small*.yml' -o -name '*hash_literal_small*.rb' | sort)
    Calculating -------------------------------------
                         compare-ruby  built-ruby
     hash_literal_small2        1.498       1.877 i/s -       1.000 times in 0.667581s 0.532656s
     hash_literal_small4        1.197       1.642 i/s -       1.000 times in 0.835375s 0.609160s
     hash_literal_small8        0.620       1.215 i/s -       1.000 times in 1.611638s 0.823090s
    
    Comparison:
                  hash_literal_small2
              built-ruby:         1.9 i/s
            compare-ruby:         1.5 i/s - 1.25x  slower
    
                  hash_literal_small4
              built-ruby:         1.6 i/s
            compare-ruby:         1.2 i/s - 1.37x  slower
    
                  hash_literal_small8
              built-ruby:         1.2 i/s
            compare-ruby:         0.6 i/s - 1.96x  slower
    ```
    
    Compared to r66255
    
    ```
    $ make benchmark ITEM=hash_literal_small COMPARE_RUBY=/Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby
    generating known_errors.inc
    known_errors.inc unchanged
    ./revision.h unchanged
    /Users/aaron/.rbenv/shims/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver \
                --executables="compare-ruby::/Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby -I.ext/common --disable-gem" \
                --executables="built-ruby::./miniruby -I./lib -I. -I.ext/common  -r./prelude --disable-gem" \
                $(find ./benchmark -maxdepth 1 -name '*hash_literal_small*.yml' -o -name '*hash_literal_small*.rb' | sort)
    Calculating -------------------------------------
                         compare-ruby  built-ruby
     hash_literal_small2        1.567       1.831 i/s -       1.000 times in 0.638056s 0.546039s
     hash_literal_small4        1.298       1.652 i/s -       1.000 times in 0.770214s 0.605182s
     hash_literal_small8        0.873       1.216 i/s -       1.000 times in 1.145304s 0.822047s
    
    Comparison:
                  hash_literal_small2
              built-ruby:         1.8 i/s
            compare-ruby:         1.6 i/s - 1.17x  slower
    
                  hash_literal_small4
              built-ruby:         1.7 i/s
            compare-ruby:         1.3 i/s - 1.27x  slower
    
                  hash_literal_small8
              built-ruby:         1.2 i/s
            compare-ruby:         0.9 i/s - 1.39x  slower
    ```

  Modified files:
    trunk/compile.c
    trunk/insns.def
    trunk/test/ruby/test_jit.rb


More information about the ruby-cvs mailing list