ruby-changes:46766
From: watson1978 <ko1@a...>
Date: Thu, 25 May 2017 13:25:44 +0900 (JST)
Subject: [ruby-changes:46766] watson1978:r58881 (trunk): Improve performance of rb_eql()
watson1978 2017-05-25 13:25:39 +0900 (Thu, 25 May 2017) New Revision: 58881 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58881 Log: 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 Modified files: trunk/internal.h trunk/object.c trunk/vm_insnhelper.c Index: object.c =================================================================== --- object.c (revision 58880) +++ object.c (revision 58881) @@ -99,7 +99,15 @@ rb_equal(VALUE obj1, VALUE obj2) https://github.com/ruby/ruby/blob/trunk/object.c#L99 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; } /* Index: internal.h =================================================================== --- internal.h (revision 58880) +++ internal.h (revision 58881) @@ -1739,6 +1739,7 @@ VALUE rb_yield_lambda(VALUE values); https://github.com/ruby/ruby/blob/trunk/internal.h#L1739 /* 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); Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 58880) +++ vm_insnhelper.c (revision 58881) @@ -1351,6 +1351,19 @@ rb_equal_opt(VALUE obj1, VALUE obj2) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1351 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/