[pypy-svn] r76894 - in pypy/branch/gc-module/pypy: module/gc module/gc/test rlib
arigo at codespeak.net
arigo at codespeak.net
Mon Sep 6 14:18:20 CEST 2010
Author: arigo
Date: Mon Sep 6 14:18:18 2010
New Revision: 76894
Added:
pypy/branch/gc-module/pypy/module/gc/referents.py (contents, props changed)
pypy/branch/gc-module/pypy/module/gc/test/test_referents.py (contents, props changed)
Modified:
pypy/branch/gc-module/pypy/module/gc/__init__.py
pypy/branch/gc-module/pypy/rlib/rgc.py
Log:
Expose the interface to app-level.
Modified: pypy/branch/gc-module/pypy/module/gc/__init__.py
==============================================================================
--- pypy/branch/gc-module/pypy/module/gc/__init__.py (original)
+++ pypy/branch/gc-module/pypy/module/gc/__init__.py Mon Sep 6 14:18:18 2010
@@ -16,6 +16,14 @@
def __init__(self, space, w_name):
ts = space.config.translation.type_system
- if ts == 'ootype':
- del self.interpleveldefs['dump_heap_stats']
+ if ts == 'lltype':
+ self.interpleveldefs.update({
+ 'get_rpy_objects': 'referents.get_rpy_objects',
+ 'get_rpy_referents': 'referents.get_rpy_referents',
+ 'get_rpy_memory_usage': 'referents.get_rpy_memory_usage',
+ 'get_objects': 'referents.get_objects',
+ 'get_referents': 'referents.get_referents',
+ 'get_memory_usage': 'referents.get_memory_usage',
+ 'GcRef': 'referents.W_GcRef',
+ })
MixedModule.__init__(self, space, w_name)
Added: pypy/branch/gc-module/pypy/module/gc/referents.py
==============================================================================
--- (empty file)
+++ pypy/branch/gc-module/pypy/module/gc/referents.py Mon Sep 6 14:18:18 2010
@@ -0,0 +1,100 @@
+from pypy.rlib import rgc
+from pypy.interpreter.baseobjspace import W_Root, Wrappable
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import ObjSpace
+from pypy.rlib.objectmodel import we_are_translated
+
+
+class W_GcRef(Wrappable):
+ def __init__(self, gcref):
+ self.gcref = gcref
+
+W_GcRef.typedef = TypeDef("GcRef")
+
+
+def wrap(space, gcref):
+ w_obj = rgc.try_cast_gcref_to_instance(W_Root, gcref)
+ if w_obj is None:
+ w_obj = space.wrap(W_GcRef(gcref))
+ return w_obj
+
+def unwrap(space, w_obj):
+ gcrefobj = space.interpclass_w(w_obj)
+ if isinstance(gcrefobj, W_GcRef):
+ gcref = gcrefobj.gcref
+ else:
+ gcref = rgc.cast_instance_to_gcref(w_obj)
+ return gcref
+
+def get_rpy_objects(space):
+ """Return a list of all objects (huge).
+ This contains a lot of GcRefs."""
+ result = rgc._get_objects()
+ return space.newlist([wrap(space, gcref) for gcref in result])
+
+def get_rpy_referents(space, w_obj):
+ """Return a list of all the referents, as reported by the GC.
+ This is likely to contain a lot of GcRefs."""
+ gcref = unwrap(space, w_obj)
+ lst = rgc._get_referents(gcref)
+ return space.newlist([wrap(space, gcref) for gcref in lst])
+
+def get_rpy_memory_usage(space, w_obj):
+ """Return the memory usage of just the given object or GcRef.
+ This does not include the internal structures of the object."""
+ gcref = unwrap(space, w_obj)
+ size = rgc._get_memory_usage(gcref)
+ return space.wrap(size)
+
+def get_objects(space):
+ """Return a list of all app-level objects."""
+ result = []
+ for gcref in rgc._get_objects():
+ w_obj = rgc.try_cast_gcref_to_instance(W_Root, gcref)
+ if w_obj is not None:
+ if we_are_translated() or hasattr(w_obj, 'typedef'):
+ result.append(w_obj)
+ return space.newlist(result)
+
+def get_referents(space, args_w):
+ """Return the list of objects that directly refer to any of objs.
+ Approximative: follow references recursively until it finds
+ app-level objects."""
+ result = []
+ pending = []
+ for w_obj in args_w:
+ pending.append(unwrap(space, w_obj))
+ i = 0
+ while i < len(pending):
+ gcref = pending[i]
+ i += 1
+ lst = rgc._get_referents(gcref)
+ for gcref in lst:
+ w_subobj = rgc.try_cast_gcref_to_instance(W_Root, gcref)
+ if w_subobj is not None:
+ result.append(w_subobj)
+ elif gcref not in pending:
+ pending.append(gcref)
+ return space.newlist(result)
+get_referents.unwrap_spec = [ObjSpace, 'args_w']
+
+def get_memory_usage(space, args_w):
+ """Return the total size of the object(s) passed as argument.
+ Approximative: follow references recursively and compute the
+ total of the sizes, stopping at other app-level objects."""
+ result = 0
+ pending = []
+ for w_obj in args_w:
+ pending.append(unwrap(space, w_obj))
+ i = 0
+ while i < len(pending):
+ gcref = pending[i]
+ i += 1
+ result += rgc._get_memory_usage(gcref)
+ lst = rgc._get_referents(gcref)
+ for gcref in lst:
+ if (rgc.try_cast_gcref_to_instance(W_Root, gcref) is None
+ and gcref not in pending):
+ pending.append(gcref)
+ return space.wrap(result)
+get_memory_usage.unwrap_spec = [ObjSpace, 'args_w']
Added: pypy/branch/gc-module/pypy/module/gc/test/test_referents.py
==============================================================================
--- (empty file)
+++ pypy/branch/gc-module/pypy/module/gc/test/test_referents.py Mon Sep 6 14:18:18 2010
@@ -0,0 +1,74 @@
+
+
+class AppTestReferents(object):
+
+ def test_get_objects(self):
+ # XXX this test should be run first, before GcRefs are created.
+ import gc
+ x = [2, 3, 4]
+ lst = gc.get_objects()
+ for found in lst:
+ if found is x:
+ break
+ else:
+ assert 0, "'x' not found in get_rpy_objects"
+ for found in lst:
+ if type(found) is gc.GcRef:
+ assert 0, "get_objects() returned a GcRef"
+
+ def test_get_rpy_objects(self):
+ import gc
+ x = [2, 3, 4]
+ lst = gc.get_rpy_objects()
+ for found in lst:
+ if found is x:
+ break
+ else:
+ assert 0, "'x' not found in get_rpy_objects"
+ for found in lst:
+ if type(found) is gc.GcRef:
+ break
+ else:
+ assert 0, "get_rpy_objects() did not return any GcRef"
+
+ def test_get_rpy_referents(self):
+ import gc
+ y = 12345
+ x = [y]
+ lst = gc.get_rpy_referents(x)
+ # After translation, 'lst' should contain the RPython-level list
+ # (as a GcStruct). Before translation, the 'wrappeditems' list.
+ print lst
+ lst2 = [x for x in lst if type(x) is gc.GcRef]
+ assert lst2 != []
+ # In any case, we should land on 'y' after one or two extra levels
+ # of indirection.
+ lst3 = []
+ for x in lst2: lst3 += gc.get_rpy_referents(x)
+ if y not in lst3:
+ lst4 = []
+ for x in lst3: lst4 += gc.get_rpy_referents(x)
+ if y not in lst4:
+ assert 0, "does not seem to reach 'y'"
+
+ def test_get_rpy_memory_usage(self):
+ import gc
+ n = gc.get_rpy_memory_usage(12345)
+ print n
+ assert 4 <= n <= 64
+
+ def test_get_referents(self):
+ import gc
+ y = 12345
+ z = 23456
+ x = [y, z]
+ lst = gc.get_referents(x)
+ assert y in lst and z in lst
+
+ def test_get_memory_usage(self):
+ import gc
+ x = [2, 5, 10]
+ n = gc.get_rpy_memory_usage(x)
+ m = gc.get_memory_usage(x)
+ print n, m
+ assert 4 <= n < m <= 128
Modified: pypy/branch/gc-module/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/gc-module/pypy/rlib/rgc.py (original)
+++ pypy/branch/gc-module/pypy/rlib/rgc.py Mon Sep 6 14:18:18 2010
@@ -321,8 +321,23 @@
return map(_GcRef, lst)
def _get_referents(gcref):
- lst = gc.get_referents(gcref._x)
- return map(_GcRef, lst)
+ x = gcref._x
+ if isinstance(x, list):
+ return map(_GcRef, x)
+ elif isinstance(x, dict):
+ return map(_GcRef, x.keys() + x.values())
+ else:
+ if hasattr(x, '__dict__'):
+ d = map(_GcRef, x.__dict__.values())
+ else:
+ d = []
+ if hasattr(type(x), '__slots__'):
+ for slot in type(x).__slots__:
+ try:
+ d.append(_GcRef(getattr(x, slot)))
+ except AttributeError:
+ pass
+ return d
def _get_memory_usage(gcref):
# approximate implementation using CPython's type info
More information about the Pypy-commit
mailing list