[pypy-svn] r17516 - in pypy/dist/pypy/rpython: . test
tismer at codespeak.net
tismer at codespeak.net
Tue Sep 13 03:19:56 CEST 2005
Author: tismer
Date: Tue Sep 13 03:19:53 2005
New Revision: 17516
Modified:
pypy/dist/pypy/rpython/rdict.py
pypy/dist/pypy/rpython/test/test_rdict.py
Log:
re-added the hash fieldto the rdict implementation.
This is a waste for many simple types, but so are other fields,
and we need to re-optimize, anyway.
Remarkable is the dramatic effect on performance:
abs.richards abs.pystone rel.richards rel.pystone
pypy-c-17439: 40929 ms 637.274 47.8 56.6
pypy-c-17512: 46105 ms 658.1 53.9 54.8
pypy-current: 33937 ms 698.415 39.6 51.7
python2.3.3: 856 ms 36081.6 1.0 1.0
richards naturally benefits much more from faster dict lookup, because it is
all about accessing instance variables.
All measurements were done on a windows notebook with 512 MB.
Threading disabled, -boehm -t-lowmem
Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py (original)
+++ pypy/dist/pypy/rpython/rdict.py Tue Sep 13 03:19:53 2005
@@ -23,6 +23,7 @@
# bool valid; # to mark if the entry is filled
# bool everused; # to mark if the entry is or has ever been filled
# DICTVALUE value;
+# int hash;
# }
#
# struct dicttable {
@@ -95,6 +96,7 @@
self.DICTVALUE = self.value_repr.lowleveltype
self.DICTENTRY = lltype.Struct("dictentry",
("key", self.DICTKEY),
+ ("hash", lltype.Signed),
("valid", lltype.Bool),
("everused", lltype.Bool),
("value", self.DICTVALUE))
@@ -305,7 +307,12 @@
entry.value = value
if entry.valid:
return
+ if dictrepr.custom_eq_hash:
+ hash = hlinvoke(dictrepr.r_rdict_hashfn, d.fnkeyhash, key)
+ else:
+ hash = dictrepr.ll_keyhash(key)
entry.key = key
+ entry.hash = hash
entry.valid = True
d.num_items += 1
if not entry.everused:
@@ -348,6 +355,7 @@
if entry.valid:
new_entry = ll_dict_lookup(d, entry.key, dictrepr)
new_entry.key = entry.key
+ new_entry.hash = entry.hash
new_entry.value = entry.value
new_entry.valid = True
new_entry.everused = True
@@ -370,16 +378,17 @@
checkingkey = entry.key
if checkingkey == key:
return entry # found the entry
- if dictrepr.custom_eq_hash:
- res = hlinvoke(dictrepr.r_rdict_eqfn, d.fnkeyeq, checkingkey, key)
- if (entries != d.entries or
- not entry.valid or entry.key != checkingkey):
- # the compare did major nasty stuff to the dict: start over
- return ll_dict_lookup(d, key, dictrepr)
- else:
- res = dictrepr.ll_keyeq is not None and dictrepr.ll_keyeq(checkingkey, key)
- if res:
- return entry # found the entry
+ if entry.hash == hash:
+ if dictrepr.custom_eq_hash:
+ res = hlinvoke(dictrepr.r_rdict_eqfn, d.fnkeyeq, checkingkey, key)
+ if (entries != d.entries or
+ not entry.valid or entry.key != checkingkey):
+ # the compare did major nasty stuff to the dict: start over
+ return ll_dict_lookup(d, key, dictrepr)
+ else:
+ res = dictrepr.ll_keyeq is not None and dictrepr.ll_keyeq(checkingkey, key)
+ if res:
+ return entry # found the entry
freeslot = lltype.nullptr(lltype.typeOf(entry).TO)
elif entry.everused:
freeslot = entry
@@ -398,16 +407,17 @@
checkingkey = entry.key
if checkingkey == key:
return entry
- if dictrepr.custom_eq_hash:
- res = hlinvoke(dictrepr.r_rdict_eqfn, d.fnkeyeq, checkingkey, key)
- if (entries != d.entries or
- not entry.valid or entry.key != checkingkey):
- # the compare did major nasty stuff to the dict: start over
- return ll_dict_lookup(d, key, dictrepr)
- else:
- res = dictrepr.ll_keyeq is not None and dictrepr.ll_keyeq(checkingkey, key)
- if res:
- return entry
+ if entry.hash == hash:
+ if dictrepr.custom_eq_hash:
+ res = hlinvoke(dictrepr.r_rdict_eqfn, d.fnkeyeq, checkingkey, key)
+ if (entries != d.entries or
+ not entry.valid or entry.key != checkingkey):
+ # the compare did major nasty stuff to the dict: start over
+ return ll_dict_lookup(d, key, dictrepr)
+ else:
+ res = dictrepr.ll_keyeq is not None and dictrepr.ll_keyeq(checkingkey, key)
+ if res:
+ return entry
elif not freeslot:
freeslot = entry
perturb >>= PERTURB_SHIFT
@@ -536,6 +546,7 @@
d_entry = d.entries[i]
entry = dict.entries[i]
d_entry.key = entry.key
+ d_entry.hash = entry.hash
d_entry.value = entry.value
d_entry.valid = entry.valid
d_entry.everused = entry.everused
Modified: pypy/dist/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rdict.py (original)
+++ pypy/dist/pypy/rpython/test/test_rdict.py Tue Sep 13 03:19:53 2005
@@ -161,6 +161,20 @@
res = interpret(func, [1])
assert len(res.entries) == rdict.DICT_INITSIZE
+def test_dict_valid_resize():
+ # see if we find our keys after resize
+ def func():
+ d = {}
+ # fill it up
+ for i in range(10):
+ d[str(i)] = 0
+ # delete again
+ for i in range(10):
+ del d[str(i)]
+ res = 0
+ # if it does not crash, we are fine. It crashes if you forget the hash field.
+ interpret(func, [])
+
def test_dict_iteration():
def func(i, j):
d = {}
More information about the Pypy-commit
mailing list