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

ruby-changes:33508

From: nobu <ko1@a...>
Date: Tue, 15 Apr 2014 12:50:01 +0900 (JST)
Subject: [ruby-changes:33508] nobu:r45589 (trunk): enum.c: make each_slice and each_cons more efficient

nobu	2014-04-15 12:49:55 +0900 (Tue, 15 Apr 2014)

  New Revision: 45589

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45589

  Log:
    enum.c: make each_slice and each_cons more efficient
    
    * enum.c (enum_each_slice, enum_each_cons): make more efficient by
      allocating less and recycling block argument arrays if possible.
      [Fixes GH-596]

  Modified files:
    trunk/ChangeLog
    trunk/enum.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 45588)
+++ ChangeLog	(revision 45589)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Apr 15 12:49:53 2014  Sam Rawlins  <sam.rawlins@g...>
+
+	* enum.c (enum_each_slice, enum_each_cons): make more efficient by
+	  allocating less and recycling block argument arrays if possible.
+	  [Fixes GH-596]
+
 Mon Apr 14 18:44:45 2014  NARUSE, Yui  <naruse@r...>
 
 	* addr2line.c (fill_lines): get base addrs in fill_lines to use it
Index: enum.c
===================================================================
--- enum.c	(revision 45588)
+++ enum.c	(revision 45589)
@@ -2058,6 +2058,9 @@ enum_each_entry(int argc, VALUE *argv, V https://github.com/ruby/ruby/blob/trunk/enum.c#L2058
     return obj;
 }
 
+#define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) == -1)
+#define nd_no_recycle u2.value
+
 static VALUE
 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
 {
@@ -2071,7 +2074,13 @@ each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST( https://github.com/ruby/ruby/blob/trunk/enum.c#L2074
 
     if (RARRAY_LEN(ary) == size) {
 	v = rb_yield(ary);
-	memo->u1.value = rb_ary_new2(size);
+
+	if (memo->nd_no_recycle) {
+	    memo->u1.value = rb_ary_new2(size);
+	}
+	else {
+	    rb_ary_clear(ary);
+	}
     }
 
     return v;
@@ -2113,11 +2122,13 @@ enum_each_slice(VALUE obj, VALUE n) https://github.com/ruby/ruby/blob/trunk/enum.c#L2122
     long size = NUM2LONG(n);
     VALUE ary;
     NODE *memo;
+    int arity;
 
     if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
     RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
     ary = rb_ary_new2(size);
-    memo = NEW_MEMO(ary, 0, size);
+    arity = rb_block_arity();
+    memo = NEW_MEMO(ary, dont_recycle_block_arg(arity), size);
     rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
     ary = memo->u1.value;
     if (RARRAY_LEN(ary) > 0) rb_yield(ary);
@@ -2139,7 +2150,10 @@ each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i https://github.com/ruby/ruby/blob/trunk/enum.c#L2150
     }
     rb_ary_push(ary, i);
     if (RARRAY_LEN(ary) == size) {
-	v = rb_yield(rb_ary_dup(ary));
+	if (memo->nd_no_recycle) {
+	    ary = rb_ary_dup(ary);
+	}
+	v = rb_yield(ary);
     }
     return v;
 }
@@ -2184,10 +2198,12 @@ enum_each_cons(VALUE obj, VALUE n) https://github.com/ruby/ruby/blob/trunk/enum.c#L2198
 {
     long size = NUM2LONG(n);
     NODE *memo;
+    int arity;
 
     if (size <= 0) rb_raise(rb_eArgError, "invalid size");
     RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
-    memo = NEW_MEMO(rb_ary_new2(size), 0, size);
+    arity = rb_block_arity();
+    memo = NEW_MEMO(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
     rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
 
     return Qnil;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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