[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]