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

ruby-changes:47189

From: normal <ko1@a...>
Date: Mon, 10 Jul 2017 08:04:50 +0900 (JST)
Subject: [ruby-changes:47189] normal:r59304 (trunk): Hash#[]= deduplicates string keys if (and only if) fstring exists

normal	2017-07-10 08:04:43 +0900 (Mon, 10 Jul 2017)

  New Revision: 59304

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59304

  Log:
    Hash#[]= deduplicates string keys if (and only if) fstring exists
    
    In typical applications, hash entries are read after being
    written to.  Blindly writing to hashes which are never read
    makes little sense. So, for any hash which is read from, an
    fstring entry for the key should already exist for the key.
    
    We no longer blindly create fstrings if the code is blindly
    setting random hash keys, preventing the performance regression
    in the reverted r43870.
    
    Regarding <https://bugs.ruby-lang.org/issues/9188>, this has a
    minimum impact on the bm_so_k_nucleotide where hash keys are set
    and not reused, performance is within 1-2% of existing cases.
    
    * hash.c: #include gc.h for rb_objspace_garbage_object_p
      (hash_aset_str): do read-only check of fstring table and
      reuse fstring if it exists and is still alive (not garbage)
      [ruby-core:81942] [Feature #13725]

  Modified files:
    trunk/hash.c
Index: hash.c
===================================================================
--- hash.c	(revision 59303)
+++ hash.c	(revision 59304)
@@ -18,6 +18,7 @@ https://github.com/ruby/ruby/blob/trunk/hash.c#L18
 #include "probes.h"
 #include "id.h"
 #include "symbol.h"
+#include "gc.h"
 
 #ifdef __APPLE__
 # ifdef HAVE_CRT_EXTERNS_H
@@ -1518,8 +1519,21 @@ hash_aset(st_data_t *key, st_data_t *val https://github.com/ruby/ruby/blob/trunk/hash.c#L1519
 static int
 hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
 {
-    if (!existing) {
-	*key = rb_str_new_frozen(*key);
+    if (!existing && !RB_OBJ_FROZEN(*key)) {
+	VALUE fstr;
+	st_table *tbl = rb_vm_fstring_table();
+
+	if (st_lookup(tbl, *key, (st_data_t *)&fstr)) {
+	    if (rb_objspace_garbage_object_p(fstr)) {
+		*key = rb_fstring(*key);
+	    }
+	    else {
+		*key = fstr;
+	    }
+	}
+	else {
+	    *key = rb_str_new_frozen(*key);
+	}
     }
     return hash_aset(key, val, arg, existing);
 }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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