mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Array#== walks both element buffers and only calls rb_equal() for a pair whose VALUEs differ. Array#eql? called rb_ary_elt() twice and rb_eql() once for every element, even though rb_eql() answers true for identical VALUEs before doing anything else. For arrays of Fixnums, Symbols, and nil, which are identical whenever they are equal, that made eql? several times slower than ==. recursive_eql() now walks the buffers the way recursive_equal() does. A pair that is not identical still goes through rb_eql(), which can run user code that resizes either array, so the length and both buffers are re-read after every such call. Arrays whose lengths came apart compare unequal, as they do under ==. Before, the shorter one read as nil past its end, so the result depended on the remaining elements of the longer one. The new tests cover an element whose eql? empties both arrays, shortens one of them, or grows both past their original capacity mid-compare.
14 lines
426 B
YAML
14 lines
426 B
YAML
prelude: |
|
|
small_ary1 = [1, :a, nil, 2]
|
|
small_ary2 = [1, :a, nil, 2]
|
|
large_ary1 = Array.new(1000) { |i| i }
|
|
large_ary2 = Array.new(1000) { |i| i }
|
|
str_ary1 = Array.new(100) { |i| i.to_s }
|
|
str_ary2 = Array.new(100) { |i| i.to_s }
|
|
|
|
benchmark:
|
|
small_ary.eql?: small_ary1.eql?(small_ary2)
|
|
large_ary.==: large_ary1 == large_ary2
|
|
large_ary.eql?: large_ary1.eql?(large_ary2)
|
|
str_ary.eql?: str_ary1.eql?(str_ary2)
|