diff options
author | watson1978 <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-05-25 04:25:39 +0000 |
---|---|---|
committer | watson1978 <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-05-25 04:25:39 +0000 |
commit | b827fdffe60d612762dd8628e3dea9b6548a4f1c (patch) | |
tree | 83cb9074b43fc9c78073acb5bc99e4169254f8e5 | |
parent | 6e0e067de31511cebec01d176f628442371db879 (diff) |
Improve performance of rb_eql()
This improvement is similar with https://github.com/ruby/ruby/pull/1552
internal.h: add declaration of rb_eql_opt() API.
vm_insnhelper.c (rb_eql_opt): add rb_eql_opt() API which provides optimized
path for #eql? method such as rb_equal_opt().
object.c (rb_eql): optimize using rb_eql_opt() such as rb_equal().
Array#eql? and some methods have used rb_eql() and Array#eql? will be faster
around 20%.
[ruby-core:80761] [Bug #13447] [Fix GH-#1589]
### Before
user system total real
1.570000 0.000000 1.570000 ( 1.569754)
### After
user system total real
1.300000 0.000000 1.300000 ( 1.303624)
### Test code
require 'benchmark'
Benchmark.bmbm do |x|
ary1 = Array.new(1000) { rand(1000) }
ary2 = Array.new(1000) { rand(1000) }
x.report do
5000000.times do
ary1.eql?(ary2)
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58881 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | object.c | 10 | ||||
-rw-r--r-- | vm_insnhelper.c | 13 |
3 files changed, 23 insertions, 1 deletions
diff --git a/internal.h b/internal.h index 6380adaacb..4c26bd2c13 100644 --- a/internal.h +++ b/internal.h @@ -1739,6 +1739,7 @@ VALUE rb_yield_lambda(VALUE values); /* vm_insnhelper.c */ VALUE rb_equal_opt(VALUE obj1, VALUE obj2); +VALUE rb_eql_opt(VALUE obj1, VALUE obj2); /* vm_method.c */ void Init_eval_method(void); @@ -99,7 +99,15 @@ rb_equal(VALUE obj1, VALUE obj2) int rb_eql(VALUE obj1, VALUE obj2) { - return RTEST(rb_funcall(obj1, id_eql, 1, obj2)); + VALUE result; + + if (obj1 == obj2) return Qtrue; + result = rb_eql_opt(obj1, obj2); + if (result == Qundef) { + result = rb_funcall(obj1, id_eql, 1, obj2); + } + if (RTEST(result)) return Qtrue; + return Qfalse; } /* diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 05aeefaa7d..a23983a5e0 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1351,6 +1351,19 @@ rb_equal_opt(VALUE obj1, VALUE obj2) return opt_eq_func(obj1, obj2, &ci, &cc); } +VALUE +rb_eql_opt(VALUE obj1, VALUE obj2) +{ + struct rb_call_info ci; + struct rb_call_cache cc; + + ci.mid = idEqlP; + cc.method_state = 0; + cc.class_serial = 0; + cc.me = NULL; + return opt_eq_func(obj1, obj2, &ci, &cc); +} + static VALUE vm_call0(rb_thread_t*, VALUE, ID, int, const VALUE*, const rb_callable_method_entry_t *); static VALUE |