From 20675167d76183d37990f68349fe877f8ee1c005 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 15 Apr 2014 03:49:55 +0000 Subject: [PATCH] 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45589 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ enum.c | 24 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 385848b668..3a6ea1e48e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Apr 15 12:49:53 2014 Sam Rawlins + + * 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 * addr2line.c (fill_lines): get base addrs in fill_lines to use it diff --git a/enum.c b/enum.c index cd2d49d6d3..8826bf3e78 100644 --- a/enum.c +++ b/enum.c @@ -2058,6 +2058,9 @@ enum_each_entry(int argc, VALUE *argv, VALUE obj) 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(i, m)) 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) 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, args)) } 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) { 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;