ruby-changes:57723
From: John <ko1@a...>
Date: Thu, 12 Sep 2019 06:23:30 +0900 (JST)
Subject: [ruby-changes:57723] 21994b7fd6 (master): Avoid rehashing keys in transform_values
https://git.ruby-lang.org/ruby.git/commit/?id=21994b7fd6 From 21994b7fd686f263544fcac1616ecf3189fb78b3 Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Wed, 11 Sep 2019 09:02:22 -0700 Subject: Avoid rehashing keys in transform_values Previously, calling transform_values would call rb_hash_aset for each key, needing to rehash it and look up its location. Instead, we can use rb_hash_stlike_foreach_with_replace to replace the values as we iterate without rehashing the keys. diff --git a/hash.c b/hash.c index b61784a..e9d994b 100644 --- a/hash.c +++ b/hash.c @@ -3129,10 +3129,16 @@ rb_hash_transform_keys_bang(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3129 } static int -transform_values_i(VALUE key, VALUE value, VALUE result) +transform_values_foreach_func(st_data_t key, st_data_t value, st_data_t argp, int error) { - VALUE new_value = rb_yield(value); - rb_hash_aset(result, key, new_value); + return ST_REPLACE; +} + +static int +transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t argp, int existing) +{ + VALUE new_value = rb_yield((VALUE)*value); + *value = new_value; return ST_CONTINUE; } @@ -3159,9 +3165,10 @@ rb_hash_transform_values(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3165 VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = rb_hash_new_with_size(RHASH_SIZE(hash)); + result = hash_dup(hash, rb_cHash, 0); + if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, transform_values_i, result); + rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, 0); } return result; @@ -3189,8 +3196,11 @@ rb_hash_transform_values_bang(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3196 { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); rb_hash_modify_check(hash); - if (!RHASH_TABLE_EMPTY_P(hash)) - rb_hash_foreach(hash, transform_values_i, hash); + + if (!RHASH_TABLE_EMPTY_P(hash)) { + rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, 0); + } + return hash; } -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/