[pypy-svn] r78370 - in pypy/branch/mapdict-without-jit/pypy: module/__pypy__ module/gc module/gc/test objspace/std objspace/std/test
arigo at codespeak.net
arigo at codespeak.net
Wed Oct 27 17:47:57 CEST 2010
Author: arigo
Date: Wed Oct 27 17:47:56 2010
New Revision: 78370
Modified:
pypy/branch/mapdict-without-jit/pypy/module/__pypy__/__init__.py
pypy/branch/mapdict-without-jit/pypy/module/__pypy__/interp_magic.py
pypy/branch/mapdict-without-jit/pypy/module/gc/interp_gc.py
pypy/branch/mapdict-without-jit/pypy/module/gc/test/test_gc.py
pypy/branch/mapdict-without-jit/pypy/objspace/std/mapdict.py
pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_dictmultiobject.py
pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_mapdict.py
Log:
(cfbolz, arigo)
Add the IndexCache to mapdict, similar to MethodCache.
Modified: pypy/branch/mapdict-without-jit/pypy/module/__pypy__/__init__.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/module/__pypy__/__init__.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/module/__pypy__/__init__.py Wed Oct 27 17:47:56 2010
@@ -23,5 +23,8 @@
'interp_magic.method_cache_counter')
self.extra_interpdef('reset_method_cache_counter',
'interp_magic.reset_method_cache_counter')
+ if self.space.config.objspace.std.withmapdict:
+ self.extra_interpdef('mapdict_cache_counter',
+ 'interp_magic.mapdict_cache_counter')
PYC_MAGIC = get_pyc_magic(self.space)
self.extra_interpdef('PYC_MAGIC', 'space.wrap(%d)' % PYC_MAGIC)
Modified: pypy/branch/mapdict-without-jit/pypy/module/__pypy__/interp_magic.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/module/__pypy__/interp_magic.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/module/__pypy__/interp_magic.py Wed Oct 27 17:47:56 2010
@@ -2,6 +2,7 @@
from pypy.interpreter.gateway import ObjSpace
from pypy.rlib.objectmodel import we_are_translated
from pypy.objspace.std.typeobject import MethodCache
+from pypy.objspace.std.mapdict import IndexCache
def internal_repr(space, w_object):
return space.wrap('%r' % (w_object,))
@@ -36,4 +37,17 @@
cache = space.fromcache(MethodCache)
cache.misses = {}
cache.hits = {}
-
+ if space.config.objspace.std.withmapdict:
+ cache = space.fromcache(IndexCache)
+ cache.misses = {}
+ cache.hits = {}
+
+def mapdict_cache_counter(space, name):
+ """Return a tuple (index_cache_hits, index_cache_misses) for lookups
+ in the mapdict cache with the given attribute name."""
+ assert space.config.objspace.std.withmethodcachecounter
+ assert space.config.objspace.std.withmapdict
+ cache = space.fromcache(IndexCache)
+ return space.newtuple([space.newint(cache.hits.get(name, 0)),
+ space.newint(cache.misses.get(name, 0))])
+mapdict_cache_counter.unwrap_spec = [ObjSpace, str]
Modified: pypy/branch/mapdict-without-jit/pypy/module/gc/interp_gc.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/module/gc/interp_gc.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/module/gc/interp_gc.py Wed Oct 27 17:47:56 2010
@@ -10,6 +10,10 @@
from pypy.objspace.std.typeobject import MethodCache
cache = space.fromcache(MethodCache)
cache.clear()
+ if space.config.objspace.std.withmapdict:
+ from pypy.objspace.std.mapdict import IndexCache
+ cache = space.fromcache(IndexCache)
+ cache.clear()
rgc.collect()
return space.wrap(0)
Modified: pypy/branch/mapdict-without-jit/pypy/module/gc/test/test_gc.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/module/gc/test/test_gc.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/module/gc/test/test_gc.py Wed Oct 27 17:47:56 2010
@@ -122,3 +122,8 @@
gc.collect() # the classes C should all go away here
for r in rlist:
assert r() is None
+
+class AppTestGcMapDictIndexCache(AppTestGcMethodCache):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withmethodcache": True,
+ "objspace.std.withmapdict": True})
Modified: pypy/branch/mapdict-without-jit/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/objspace/std/mapdict.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/objspace/std/mapdict.py Wed Oct 27 17:47:56 2010
@@ -1,4 +1,5 @@
from pypy.rlib import jit, objectmodel, debug
+from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.interpreter.baseobjspace import W_Root
from pypy.objspace.std.dictmultiobject import W_DictMultiObject
@@ -40,7 +41,44 @@
def delete(self, obj, selector):
return None
+ @jit.purefunction
def index(self, selector):
+ if self.space.config.objspace.std.withmethodcache:
+ return self._index_cache(selector)
+ else:
+ return self._index(selector)
+
+ def _index_cache(self, selector):
+ space = self.space
+ cache = space.fromcache(IndexCache)
+ SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp
+ SHIFT1 = SHIFT2 - 5
+ attrs_as_int = objectmodel.current_object_addr_as_int(self)
+ # ^^^Note: see comment in typeobject.py for
+ # _pure_lookup_where_with_method_cache()
+ hash_selector = objectmodel.compute_hash(selector)
+ product = intmask(attrs_as_int * hash_selector)
+ index_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2
+ # ^^^Note2: same comment too
+ cached_attr = cache.attrs[index_hash]
+ if cached_attr is self:
+ cached_selector = cache.selectors[index_hash]
+ if cached_selector == selector:
+ index = cache.indices[index_hash]
+ if space.config.objspace.std.withmethodcachecounter:
+ name = selector[0]
+ cache.hits[name] = cache.hits.get(name, 0) + 1
+ return index
+ index = self._index(selector)
+ cache.attrs[index_hash] = self
+ cache.selectors[index_hash] = selector
+ cache.indices[index_hash] = index
+ if space.config.objspace.std.withmethodcachecounter:
+ name = selector[0]
+ cache.misses[name] = cache.misses.get(name, 0) + 1
+ return index
+
+ def _index(self, selector):
return -1
def copy(self, obj):
@@ -221,10 +259,10 @@
self._copy_attr(obj, new_obj)
return new_obj
- def index(self, selector):
+ def _index(self, selector):
if selector == self.selector:
return self.position
- return self.back.index(selector)
+ return self.back._index(selector)
def copy(self, obj):
new_obj = self.back.copy(obj)
@@ -267,6 +305,23 @@
# RPython reasons
w_obj._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
+class IndexCache(object):
+ def __init__(self, space):
+ assert space.config.objspace.std.withmethodcache
+ SIZE = 1 << space.config.objspace.std.methodcachesizeexp
+ self.attrs = [None] * SIZE
+ self.selectors = [None] * SIZE
+ self.indices = [0] * SIZE
+ if space.config.objspace.std.withmethodcachecounter:
+ self.hits = {}
+ self.misses = {}
+
+ def clear(self):
+ for i in range(len(self.attrs)):
+ self.attrs[i] = None
+ for i in range(len(self.selectors)):
+ self.selectors[i] = None
+
# ____________________________________________________________
# object implementation
Modified: pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_dictmultiobject.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_dictmultiobject.py Wed Oct 27 17:47:56 2010
@@ -607,6 +607,7 @@
withdictmeasurement = False
withsmalldicts = False
withcelldict = False
+ withmethodcache = False
class opcodes:
CALL_LIKELY_BUILTIN = False
Modified: pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_mapdict.py
==============================================================================
--- pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_mapdict.py (original)
+++ pypy/branch/mapdict-without-jit/pypy/objspace/std/test/test_mapdict.py Wed Oct 27 17:47:56 2010
@@ -24,7 +24,6 @@
hasdict = False
def test_plain_attribute():
- space = " "
w_cls = "class"
aa = PlainAttribute(("b", DICT),
PlainAttribute(("a", DICT),
@@ -778,3 +777,52 @@
assert res == (0, 0, 1)
res = self.check(f, 'x')
assert res == (0, 0, 1)
+
+class AppTestCaching(AppTestWithMapDict):
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.withmethodcachecounter": True,
+ "objspace.std.withmapdict": True,
+ "objspace.opcodes.CALL_METHOD": True})
+
+ def test_mix_classes(self):
+ import __pypy__
+ class A(object):
+ def f(self):
+ return 42
+ class B(object):
+ def f(self):
+ return 43
+ class C(object):
+ def f(self):
+ return 44
+ l = [A(), B(), C()] * 10
+ __pypy__.reset_method_cache_counter()
+ # 'exec' to make sure that a.f() is compiled with CALL_METHOD
+ exec """for i, a in enumerate(l):
+ assert a.f() == 42 + i % 3
+"""
+ cache_counter = __pypy__.mapdict_cache_counter("f")
+ assert cache_counter[0] >= 15
+ assert cache_counter[1] >= 3 # should be (27, 3)
+ assert sum(cache_counter) == 30
+
+ def test_mix_classes_attribute(self):
+ import __pypy__
+ class A(object):
+ def __init__(self):
+ self.x = 42
+ class B(object):
+ def __init__(self):
+ self.x = 43
+ class C(object):
+ def __init__(self):
+ self.x = 44
+ l = [A(), B(), C()] * 10
+ __pypy__.reset_method_cache_counter()
+ for i, a in enumerate(l):
+ assert a.x == 42 + i % 3
+ cache_counter = __pypy__.mapdict_cache_counter("x")
+ assert cache_counter[0] >= 15
+ assert cache_counter[1] >= 3 # should be (27, 3)
+ assert sum(cache_counter) == 30
More information about the Pypy-commit
mailing list