Improve performance of implicit type conversion

To convert the object implicitly, it has had two parts in convert_type() which are
  1. lookink up the method's id
  2. calling the method

Seems that strncmp() and strcmp() in convert_type() are slightly heavy to look up
the method's id for type conversion.

This patch will add and use internal APIs (rb_convert_type_with_id, rb_check_convert_type_with_id)
to call the method without looking up the method's id when convert the object.

Array#flatten -> 19 % up
Array#+       ->  3 % up

[ruby-dev:50024] [Bug #13341] [Fix GH-1537]

### Before
       Array#flatten    104.119k (± 1.1%) i/s -    525.690k in   5.049517s
             Array#+      1.993M (± 1.8%) i/s -     10.010M in   5.024258s

### After
       Array#flatten    124.005k (± 1.0%) i/s -    624.240k in   5.034477s
             Array#+      2.058M (± 4.8%) i/s -     10.302M in   5.019328s

### Test Code
require 'benchmark/ips'

class Foo
  def to_ary
    [1,2,3]
  end
end

Benchmark.ips do |x|

  ary = []
  100.times { |i| ary << i }
  array = [ary]

  x.report "Array#flatten" do |i|
    i.times { array.flatten }
  end

  x.report "Array#+" do |i|
    obj = Foo.new
    i.times { array + obj }
  end

end

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58978 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
watson1978 2017-05-31 12:30:57 +00:00
parent cc50ed4a50
commit d0015e4ac6
16 changed files with 94 additions and 57 deletions

View file

@ -642,13 +642,13 @@ rb_assoc_new(VALUE car, VALUE cdr)
static VALUE
to_ary(VALUE ary)
{
return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
}
VALUE
rb_check_array_type(VALUE ary)
{
return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
}
/*
@ -2012,7 +2012,7 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
val = tmp;
goto str_join;
}
tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
tmp = rb_check_convert_type_with_id(val, T_ARRAY, "Array", idTo_ary);
if (!NIL_P(tmp)) {
obj = val;
val = tmp;