[pypy-svn] r58737 - pypy/dist/pypy/translator/tool
xoraxax at codespeak.net
xoraxax at codespeak.net
Tue Oct 7 14:30:20 CEST 2008
Author: xoraxax
Date: Tue Oct 7 14:30:19 2008
New Revision: 58737
Modified:
pypy/dist/pypy/translator/tool/staticsizereport.py
Log:
(cfbolz, antocuni, xoraxax) Add reporting for static data in RPython programs by module. Can be used e.g. on the pdb prompt after source generation.
Modified: pypy/dist/pypy/translator/tool/staticsizereport.py
==============================================================================
--- pypy/dist/pypy/translator/tool/staticsizereport.py (original)
+++ pypy/dist/pypy/translator/tool/staticsizereport.py Tue Oct 7 14:30:19 2008
@@ -1,10 +1,34 @@
from __future__ import division
-from pypy.rpython.lltypesystem.lltype import typeOf, _ptr, Ptr
+from pypy.rpython.lltypesystem.lltype import typeOf, _ptr, Ptr, ContainerType
from pypy.rpython.lltypesystem import llmemory
from pypy.rpython.memory.lltypelayout import convert_offset_to_int
-def guess_size(obj):
+
+def guess_module(graph):
+ func = getattr(graph, 'func', None)
+ name = '<unknown>'
+ if func is not None:
+ newname = func.func_globals.get('__name__', None)
+ if newname is not None:
+ name = newname
+ else:
+ if func.__module__:
+ name = func.__module__
+ return name
+
+
+def values_to_nodes(database, values):
+ nodes = []
+ for value in values:
+ if isinstance(typeOf(value), Ptr) and isinstance(typeOf(value._obj), ContainerType):
+ node = database.getcontainernode(value._obj)
+ if node.nodekind != 'func':
+ nodes.append(node)
+ return nodes
+
+
+def guess_size_obj(obj):
TYPE = typeOf(obj)
ptr = _ptr(Ptr(TYPE), obj)
if TYPE._is_varsize():
@@ -22,24 +46,94 @@
return convert_offset_to_int(llmemory.sizeof(TYPE, length))
+def guess_size(database, node, recursive=None):
+ obj = node.obj
+ size = guess_size_obj(obj)
+ if recursive is None:
+ return size
+ if node in recursive:
+ return 0
+ recursive.add(node)
+ for dep in values_to_nodes(database, node.enum_dependencies()):
+ recursive.add(dep)
+ size += guess_size(database, dep, recursive)
+ return size
+
+
def by_lltype(obj):
return typeOf(obj)
-def group_static_size(database, grouper=by_lltype):
+def group_static_size(database, nodes, grouper=by_lltype, recursive=None):
totalsize = {}
numobjects = {}
- for node in database.globalcontainers():
+ for node in nodes:
obj = node.obj
group = grouper(obj)
- totalsize[group] = totalsize.get(group, 0) + guess_size(obj)
+ totalsize[group] = totalsize.get(group, 0) + guess_size(database, node, recursive)
numobjects[group] = numobjects.get(group, 0) + 1
return totalsize, numobjects
-def print_static_size(database, grouper=by_lltype):
- totalsize, numobjects = group_static_size(database, grouper)
+def make_report_static_size(database, nodes, grouper, recursive=None):
+ totalsize, numobjects = group_static_size(database, nodes, grouper, recursive)
l = [(size, key) for key, size in totalsize.iteritems()]
l.sort()
l.reverse()
+ sizesum = 0
+ report = []
for size, key in l:
- print key, size, numobjects[key], size / numobjects[key]
+ sizesum += size
+ report.append((key, size, numobjects[key], size / numobjects[key]))
+ return sizesum, report
+
+def format_report_line(line):
+ return str(line[0])[:50] + " " + " ".join([str(x) for x in line[1:]])
+
+
+def print_report_static_size(database, grouper=by_lltype):
+ " Reports all objects with a specified grouper. "
+ _, report = report_static_size(database.globalcontainers(), grouper)
+ for line in report:
+ print format_report_line(line)
+
+
+def print_aggregated_values_by_module_and_type(database, count_modules_separately=False):
+ " Reports all objects by module and by lltype. "
+ modules = {}
+ reports = []
+ funcnodes = [node for node in database.globalcontainers()
+ if node.nodekind == "func"]
+ # extract all prebuilt nodes per module
+ for node in funcnodes:
+ graph = getattr(node.obj, 'graph', None)
+ if not graph:
+ continue
+ nodes_set = modules.setdefault(guess_module(graph), set())
+ assert len(node.funcgens) == 1
+ nodes_set.update(values_to_nodes(database, node.funcgens[0].all_cached_consts))
+ modules = modules.items()
+ # make sure that gc modules are reported latest to avoid them eating all objects
+ def gc_module_key(tup):
+ if "module.gc" in tup[0]:
+ return ("\xff", ) + tup
+ return tup
+ modules.sort(key=gc_module_key)
+
+ # report sizes per module
+ seen = set()
+ for modulename, nodes in modules:
+ if count_modules_separately:
+ seen = set()
+ if not nodes:
+ continue
+ size, report = make_report_static_size(database, nodes, by_lltype, seen)
+ reports.append((size, modulename, report))
+ reports.sort()
+ reports.reverse()
+ for size, modulename, report in reports:
+ if not size:
+ continue
+ print "########### %i %s ####################################" % (size, modulename)
+ for line in report:
+ print " " * 4 + format_report_line(line)
+ print
More information about the Pypy-commit
mailing list