diff options
author | watson1978 <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-05-25 04:25:37 +0000 |
---|---|---|
committer | watson1978 <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-05-25 04:25:37 +0000 |
commit | 6e0e067de31511cebec01d176f628442371db879 (patch) | |
tree | 8639ff292c0554ce5693251523ec8e5ac654170e /array.c | |
parent | 944c455b38f85c5fa1b91390d43d89b692e4c812 (diff) |
Improve performance of rb_equal()
* object.c (rb_equal): add optimized path to compare the objects using
rb_equal_opt(). Previously, if not same objects were given, rb_equal() would
call `==' method via rb_funcall() which took a long time.
rb_equal_opt() has provided faster comparing for Fixnum/Float/String objects.
Now, Time#eql? uses rb_equal() to compare with argument object and it will
be faster around 40% on 64-bit environment.
* array.c (rb_ary_index): remove redundant rb_equal_opt() calling.
Now, rb_equal() was optimized using rb_equal_opt().
If rb_equal_opt() returns Qundef, it will invoke rb_equal() -> rb_equal_opt(),
and it will cause the performance regression.
So, this patch will remove first redundant rb_equal_opt() calling.
* array.c (rb_ary_rindex): ditto.
* array.c (rb_ary_includes): ditto.
[ruby-core:80360] [Bug #13365] [Fix GH-#1552]
### Before
Time#eql? with other 7.309M (± 1.4%) i/s - 36.647M in 5.014964s
Array#index(val) 1.433M (± 1.2%) i/s - 7.207M in 5.030942s
Array#rindex(val) 1.418M (± 1.6%) i/s - 7.103M in 5.009164s
Array#include?(val) 1.451M (± 0.9%) i/s - 7.295M in 5.026392s
### After
Time#eql? with other 10.321M (± 1.9%) i/s - 51.684M in 5.009203s
Array#index(val) 1.474M (± 0.9%) i/s - 7.433M in 5.044384s
Array#rindex(val) 1.449M (± 1.7%) i/s - 7.292M in 5.034436s
Array#include?(val) 1.466M (± 1.7%) i/s - 7.373M in 5.030047s
### Test code
require 'benchmark/ips'
Benchmark.ips do |x|
t1 = Time.now
t2 = Time.now
x.report "Time#eql? with other" do |i|
i.times { t1.eql?(t2) }
end
# Benchmarks to check whether it didn't introduce the regression
obj = Object.new
x.report "Array#index(val)" do |i|
ary = [1, 2, true, false, obj]
i.times { ary.index(obj) }
end
x.report "Array#rindex(val)" do |i|
ary = [1, 2, true, false, obj].reverse
i.times { ary.rindex(obj) }
end
x.report "Array#include?(val)" do |i|
ary = [1, 2, true, false, obj]
i.times { ary.include?(obj) }
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58880 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 39 |
1 files changed, 7 insertions, 32 deletions
@@ -1465,9 +1465,8 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary) static VALUE rb_ary_index(int argc, VALUE *argv, VALUE ary) { - const VALUE *ptr; VALUE val; - long i, len; + long i; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0); @@ -1482,20 +1481,11 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary) val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used"); - len = RARRAY_LEN(ary); - ptr = RARRAY_CONST_PTR(ary); - for (i=0; i<len; i++) { - VALUE e = ptr[i]; - switch (rb_equal_opt(e, val)) { - case Qundef: - if (!rb_equal(e, val)) break; - case Qtrue: + for (i=0; i<RARRAY_LEN(ary); i++) { + VALUE e = RARRAY_AREF(ary, i); + if (rb_equal(e, val)) { return LONG2NUM(i); - case Qfalse: - continue; } - len = RARRAY_LEN(ary); - ptr = RARRAY_CONST_PTR(ary); } return Qnil; } @@ -1527,7 +1517,6 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary) static VALUE rb_ary_rindex(int argc, VALUE *argv, VALUE ary) { - const VALUE *ptr; VALUE val; long i = RARRAY_LEN(ary), len; @@ -1546,21 +1535,11 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary) val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used"); - ptr = RARRAY_CONST_PTR(ary); while (i--) { - VALUE e = ptr[i]; - switch (rb_equal_opt(e, val)) { - case Qundef: - if (!rb_equal(e, val)) break; - case Qtrue: + VALUE e = RARRAY_AREF(ary, i); + if (rb_equal(e, val)) { return LONG2NUM(i); - case Qfalse: - continue; } - if (i > (len = RARRAY_LEN(ary))) { - i = len; - } - ptr = RARRAY_CONST_PTR(ary); } return Qnil; } @@ -3992,11 +3971,7 @@ rb_ary_includes(VALUE ary, VALUE item) for (i=0; i<RARRAY_LEN(ary); i++) { e = RARRAY_AREF(ary, i); - switch (rb_equal_opt(e, item)) { - case Qundef: - if (rb_equal(e, item)) return Qtrue; - break; - case Qtrue: + if (rb_equal(e, item)) { return Qtrue; } } |