ruby-changes:42967
From: mrkn <ko1@a...>
Date: Wed, 18 May 2016 09:55:00 +0900 (JST)
Subject: [ruby-changes:42967] mrkn:r55041 (trunk): Optimize each_sum for hashes
mrkn 2016-05-18 09:54:52 +0900 (Wed, 18 May 2016) New Revision: 55041 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55041 Log: Optimize each_sum for hashes * enum.c (enum_sum, hash_sum, hash_sum_i, enum_sum_i, sum_iter): Optimize for hashes when each method isn't redefined. Modified files: trunk/ChangeLog trunk/enum.c Index: ChangeLog =================================================================== --- ChangeLog (revision 55040) +++ ChangeLog (revision 55041) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed May 18 09:52:00 2016 Kenta Murata <mrkn@m...> + + * enum.c (enum_sum, hash_sum, hash_sum_i, enum_sum_i, sum_iter): + Optimize for hashes when each method isn't redefined. + Wed May 18 09:14:00 2016 Kenta Murata <mrkn@m...> * enum.c (enum_sum, int_range_sum): Extract int_range_sum from Index: enum.c =================================================================== --- enum.c (revision 55040) +++ enum.c (revision 55041) @@ -13,6 +13,8 @@ https://github.com/ruby/ruby/blob/trunk/enum.c#L13 #include "ruby/util.h" #include "id.h" +#include <assert.h> + VALUE rb_mEnumerable; static ID id_next; @@ -3569,18 +3571,17 @@ struct enum_sum_memo { https://github.com/ruby/ruby/blob/trunk/enum.c#L3571 int float_value; }; -static VALUE -enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) +static void +sum_iter(VALUE i, struct enum_sum_memo *memo) { - struct enum_sum_memo *memo = (struct enum_sum_memo *)args; + assert(memo != NULL); + long n = memo->n; VALUE v = memo->v; VALUE r = memo->r; double f = memo->f; double c = memo->c; - ENUM_WANT_SVALUE(); - if (memo->block_given) i = rb_yield(i); @@ -3662,10 +3663,32 @@ enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLI https://github.com/ruby/ruby/blob/trunk/enum.c#L3663 memo->r = r; memo->f = f; memo->c = c; +} +static VALUE +enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) +{ + ENUM_WANT_SVALUE(); + sum_iter(i, (struct enum_sum_memo *) args); return Qnil; } +static int +hash_sum_i(VALUE key, VALUE value, VALUE arg) +{ + sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg); + return ST_CONTINUE; +} + +static void +hash_sum(VALUE hash, struct enum_sum_memo *memo) +{ + assert(RB_TYPE_P(hash, T_HASH)); + assert(memo != NULL); + + rb_hash_foreach(hash, hash_sum_i, (VALUE)memo); +} + static VALUE int_range_sum(VALUE beg, VALUE end, int excl, VALUE init) { @@ -3743,7 +3766,11 @@ enum_sum(int argc, VALUE* argv, VALUE ob https://github.com/ruby/ruby/blob/trunk/enum.c#L3766 } } - rb_block_call(obj, id_each, 0, 0, enum_sum_iter_i, (VALUE)&memo); + if (RB_TYPE_P(obj, T_HASH) && + rb_method_basic_definition_p(CLASS_OF(obj), id_each)) + hash_sum(obj, &memo); + else + rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo); if (memo.float_value) { return DBL2NUM(memo.f); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/