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/