mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
944c455b38
commit
6e0e067de3
2 changed files with 11 additions and 33 deletions
39
array.c
39
array.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
5
object.c
5
object.c
|
@ -88,7 +88,10 @@ rb_equal(VALUE obj1, VALUE obj2)
|
|||
VALUE result;
|
||||
|
||||
if (obj1 == obj2) return Qtrue;
|
||||
result = rb_funcall(obj1, id_eq, 1, obj2);
|
||||
result = rb_equal_opt(obj1, obj2);
|
||||
if (result == Qundef) {
|
||||
result = rb_funcall(obj1, id_eq, 1, obj2);
|
||||
}
|
||||
if (RTEST(result)) return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue