зеркало из https://github.com/github/ruby.git
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
952e444877
Коммит
eb8f91866e
|
@ -1,3 +1,11 @@
|
||||||
|
Mon Jul 29 21:29:48 2013 Masaki Matsushita <glass.saga@gmail.com>
|
||||||
|
|
||||||
|
* 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@iDaemons.org>
|
Mon Jul 29 21:15:30 2013 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
* test/ruby/test_lazy_enumerator.rb
|
* test/ruby/test_lazy_enumerator.rb
|
||||||
|
|
52
hash.c
52
hash.c
|
@ -2122,6 +2122,32 @@ rb_hash_merge(VALUE hash1, VALUE hash2)
|
||||||
return rb_hash_update(rb_obj_dup(hash1), hash2);
|
return rb_hash_update(rb_obj_dup(hash1), hash2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static int
|
||||||
assoc_i(VALUE key, VALUE val, VALUE arg)
|
assoc_i(VALUE key, VALUE val, VALUE arg)
|
||||||
{
|
{
|
||||||
|
@ -2149,11 +2175,33 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VALUE
|
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];
|
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;
|
args[1] = Qnil;
|
||||||
rb_hash_foreach(hash, assoc_i, (VALUE)args);
|
rb_hash_foreach(hash, assoc_i, (VALUE)args);
|
||||||
return args[1];
|
return args[1];
|
||||||
|
|
|
@ -879,6 +879,14 @@ class TestHash < Test::Unit::TestCase
|
||||||
assert_equal([1.0,1], {1.0=>1}.assoc(1))
|
assert_equal([1.0,1], {1.0=>1}.assoc(1))
|
||||||
end
|
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
|
def test_rassoc
|
||||||
assert_equal([3,4], {1=>2, 3=>4, 5=>6}.rassoc(4))
|
assert_equal([3,4], {1=>2, 3=>4, 5=>6}.rassoc(4))
|
||||||
assert_nil({1=>2, 3=>4, 5=>6}.rassoc(3))
|
assert_nil({1=>2, 3=>4, 5=>6}.rassoc(3))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче