1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Improve Enumerable#tally performance

Iteration per second (i/s)

|       |compare-ruby|built-ruby|
|:------|-----------:|---------:|
|tally  |      52.814|   114.936|
|       |           -|     2.18x|
This commit is contained in:
Nobuyoshi Nakada 2021-03-16 22:14:56 +09:00
parent e61e9bcfb2
commit 382d3a4516
No known key found for this signature in database
GPG key ID: 7CD2805BFA3770C6
Notes: git 2021-03-17 00:01:18 +09:00
2 changed files with 18 additions and 6 deletions

4
benchmark/enum_tally.yml Normal file
View file

@ -0,0 +1,4 @@
prelude: |
list = ("aaa".."zzz").to_a*10
benchmark:
tally: list.tally

20
enum.c
View file

@ -1008,11 +1008,11 @@ enum_group_by(VALUE obj)
return enum_hashify(obj, 0, 0, group_by_i); return enum_hashify(obj, 0, 0, group_by_i);
} }
static void static int
tally_up(VALUE hash, VALUE group) tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing)
{ {
VALUE tally = rb_hash_aref(hash, group); VALUE tally = (VALUE)*value;
if (NIL_P(tally)) { if (!existing) {
tally = INT2FIX(1); tally = INT2FIX(1);
} }
else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) { else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) {
@ -1021,14 +1021,22 @@ tally_up(VALUE hash, VALUE group)
else { else {
tally = rb_big_plus(tally, INT2FIX(1)); tally = rb_big_plus(tally, INT2FIX(1));
} }
rb_hash_aset(hash, group, tally); *value = (st_data_t)tally;
return ST_CONTINUE;
}
static VALUE
rb_enum_tally_up(VALUE hash, VALUE group)
{
rb_hash_stlike_update(hash, group, tally_up, 0);
return hash;
} }
static VALUE static VALUE
tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
{ {
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
tally_up(hash, i); rb_enum_tally_up(hash, i);
return Qnil; return Qnil;
} }