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

ruby-changes:30185

From: glass <ko1@a...>
Date: Mon, 29 Jul 2013 21:39:35 +0900 (JST)
Subject: [ruby-changes:30185] glass:r42237 (trunk): * hash.c (rb_hash_assoc): performance improvement by replacing

glass	2013-07-29 21:39:21 +0900 (Mon, 29 Jul 2013)

  New Revision: 42237

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42237

  Log:
    * hash.c (rb_hash_assoc): performance improvement by replacing
      compare function in RHASH(hash)->ntbl->type temporarily like r42224.
      it falls back to rb_hash_foreach() if st_lookup() doesn't find the key.
    
    * test/ruby/test_hash.rb: add a test for above.

  Modified files:
    trunk/ChangeLog
    trunk/hash.c
    trunk/test/ruby/test_hash.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42236)
+++ ChangeLog	(revision 42237)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Jul 29 21:29:48 2013  Masaki Matsushita  <glass.saga@g...>
+
+	* hash.c (rb_hash_assoc): performance improvement by replacing
+	  compare function in RHASH(hash)->ntbl->type temporarily like r42224.
+	  it falls back to rb_hash_foreach() if st_lookup() doesn't find the key.
+
+	* test/ruby/test_hash.rb: add a test for above.
+
 Mon Jul 29 21:15:30 2013  Akinori MUSHA  <knu@i...>
 
 	* test/ruby/test_lazy_enumerator.rb
Index: hash.c
===================================================================
--- hash.c	(revision 42236)
+++ hash.c	(revision 42237)
@@ -2123,6 +2123,32 @@ rb_hash_merge(VALUE hash1, VALUE hash2) https://github.com/ruby/ruby/blob/trunk/hash.c#L2123
 }
 
 static int
+assoc_cmp(VALUE a, VALUE b)
+{
+    return !RTEST(rb_equal(a, b));
+}
+
+static VALUE
+lookup2_call(VALUE arg)
+{
+    VALUE *args = (VALUE *)arg;
+    return rb_hash_lookup2(args[0], args[1], Qundef);
+}
+
+struct reset_hash_type_arg {
+    VALUE hash;
+    const struct st_hash_type *orighash;
+};
+
+static VALUE
+reset_hash_type(VALUE arg)
+{
+    struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
+    RHASH(p->hash)->ntbl->type = p->orighash;
+    return Qundef;
+}
+
+static int
 assoc_i(VALUE key, VALUE val, VALUE arg)
 {
     VALUE *args = (VALUE *)arg;
@@ -2149,11 +2175,33 @@ assoc_i(VALUE key, VALUE val, VALUE arg) https://github.com/ruby/ruby/blob/trunk/hash.c#L2175
  */
 
 VALUE
-rb_hash_assoc(VALUE hash, VALUE obj)
+rb_hash_assoc(VALUE hash, VALUE key)
 {
+    st_table *table;
+    const struct st_hash_type *orighash;
     VALUE args[2];
 
-    args[0] = obj;
+    if (RHASH_EMPTY_P(hash)) return Qnil;
+    table = RHASH(hash)->ntbl;
+    orighash = table->type;
+
+    if (orighash != &identhash) {
+	VALUE value;
+	struct reset_hash_type_arg ensure_arg;
+	struct st_hash_type assochash;
+
+	assochash.compare = assoc_cmp;
+	assochash.hash = orighash->hash;
+	table->type = &assochash;
+	args[0] = hash;
+	args[1] = key;
+	ensure_arg.hash = hash;
+	ensure_arg.orighash = orighash;
+	value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
+	if (value != Qundef) return rb_assoc_new(key, value);
+    }
+
+    args[0] = key;
     args[1] = Qnil;
     rb_hash_foreach(hash, assoc_i, (VALUE)args);
     return args[1];
Index: test/ruby/test_hash.rb
===================================================================
--- test/ruby/test_hash.rb	(revision 42236)
+++ test/ruby/test_hash.rb	(revision 42237)
@@ -879,6 +879,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L879
     assert_equal([1.0,1], {1.0=>1}.assoc(1))
   end
 
+  def test_assoc_compare_by_identity
+    h = {}
+    h.compare_by_identity
+    h["a"] = 1
+    h["a"] = 2
+    assert_equal(["a",1], h.assoc("a"))
+  end
+
   def test_rassoc
     assert_equal([3,4], {1=>2, 3=>4, 5=>6}.rassoc(4))
     assert_nil({1=>2, 3=>4, 5=>6}.rassoc(3))

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

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