[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]