aboutsummaryrefslogtreecommitdiffstats
path: root/enum.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-03-16 22:14:56 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-03-16 23:06:41 +0900
commit382d3a4516a8177acbd23e8f87e766e38cce36a8 (patch)
tree62d7c47e823141e39a9720d4a90d9590cbb894d7 /enum.c
parente61e9bcfb27580ae52b46fc7ca49c38f8fdeb8cd (diff)
downloadruby-382d3a4516a8177acbd23e8f87e766e38cce36a8.tar.gz
Improve Enumerable#tally performance
Iteration per second (i/s) | |compare-ruby|built-ruby| |:------|-----------:|---------:| |tally | 52.814| 114.936| | | -| 2.18x|
Diffstat (limited to 'enum.c')
-rw-r--r--enum.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/enum.c b/enum.c
index ef35f9bb7c..d8eefc8cbf 100644
--- a/enum.c
+++ b/enum.c
@@ -1008,11 +1008,11 @@ enum_group_by(VALUE obj)
return enum_hashify(obj, 0, 0, group_by_i);
}
-static void
-tally_up(VALUE hash, VALUE group)
+static int
+tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing)
{
- VALUE tally = rb_hash_aref(hash, group);
- if (NIL_P(tally)) {
+ VALUE tally = (VALUE)*value;
+ if (!existing) {
tally = INT2FIX(1);
}
else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) {
@@ -1021,14 +1021,22 @@ tally_up(VALUE hash, VALUE group)
else {
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
tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
{
ENUM_WANT_SVALUE();
- tally_up(hash, i);
+ rb_enum_tally_up(hash, i);
return Qnil;
}