[pypy-svn] r71393 - in pypy/trunk/pypy/jit/tool: . test
fijal at codespeak.net
fijal at codespeak.net
Mon Feb 22 05:32:49 CET 2010
Author: fijal
Date: Mon Feb 22 05:32:47 2010
New Revision: 71393
Added:
pypy/trunk/pypy/jit/tool/otherviewer.py (contents, props changed)
pypy/trunk/pypy/jit/tool/test/test_otherviewer.py (contents, props changed)
Log:
A viewer for logs
Added: pypy/trunk/pypy/jit/tool/otherviewer.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/jit/tool/otherviewer.py Mon Feb 22 05:32:47 2010
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+""" Usage: otherviewer.py loopfile
+"""
+
+import optparse
+import sys
+import re
+
+import autopath
+from pypy.translator.tool.graphpage import GraphPage
+from pypy.translator.tool.make_dot import DotGen
+from pypy.tool import logparser
+
+class Page(GraphPage):
+ def compute(self, graphs):
+ dotgen = DotGen('trace')
+ memo = set()
+ for graph in graphs:
+ graph.generate(dotgen, memo)
+ self.source = dotgen.generate(target=None)
+
+class BasicBlock(object):
+ counter = 0
+
+ def __init__(self, content):
+ self.content = content
+ self.no = self.counter
+ self.__class__.counter += 1
+
+ def name(self):
+ return 'node' + str(self.no)
+
+ def getcolor(self):
+ if self.ratio > 8:
+ return 'red'
+ elif self.ratio > 5:
+ return 'yellow'
+ return 'green'
+
+ def generate(self, dotgen, memo):
+ dotgen.emit_node(self.name(), label=self.content,
+ shape='box', fillcolor=self.getcolor())
+
+class FinalBlock(BasicBlock):
+ def __init__(self, content, target):
+ self.target = target
+ BasicBlock.__init__(self, content)
+
+ def postprocess(self, loops, memo):
+ postprocess_loop(self.target, loops, memo)
+
+ def generate(self, dotgen, memo):
+ if self in memo:
+ return
+ memo.add(self)
+ BasicBlock.generate(self, dotgen, memo)
+ if self.target is not None:
+ dotgen.emit_edge(self.name(), self.target.name())
+ self.target.generate(dotgen, memo)
+
+class Block(BasicBlock):
+ def __init__(self, content, left, right):
+ self.left = left
+ self.right = right
+ BasicBlock.__init__(self, content)
+
+ def postprocess(self, loops, memo):
+ postprocess_loop(self.left, loops, memo)
+ postprocess_loop(self.right, loops, memo)
+
+ def generate(self, dotgen, memo):
+ if self in memo:
+ return
+ memo.add(self)
+ BasicBlock.generate(self, dotgen, memo)
+ dotgen.emit_edge(self.name(), self.left.name())
+ dotgen.emit_edge(self.name(), self.right.name())
+ self.left.generate(dotgen, memo)
+ self.right.generate(dotgen, memo)
+
+def split_one_loop(allloops, guard_s, guard_content):
+ for i, loop in enumerate(allloops):
+ content = loop.content
+ pos = content.find(guard_s + '>')
+ if pos != -1:
+ newpos = content.rfind("\n", 0, pos)
+ oldpos = content.find("\n", pos)
+ assert newpos != -1
+ if oldpos == -1:
+ oldpos = len(content)
+ allloops[i] = Block(content[:oldpos],
+ FinalBlock(content[oldpos:], None),
+ FinalBlock(content[newpos + 1:oldpos] + "\n" +
+ guard_content, None))
+ allloops[i].guard_s = guard_s
+
+def splitloops(loops):
+ real_loops = []
+ for loop in loops:
+ firstline = loop[:loop.find("\n")]
+ m = re.match('# Loop (\d+)', firstline)
+ if m:
+ no = int(m.group(1))
+ assert len(real_loops) == no
+ real_loops.append(FinalBlock(loop, None))
+ else:
+ m = re.search("bridge out of Guard (\d+)", firstline)
+ assert m
+ guard_s = 'Guard' + m.group(1)
+ split_one_loop(real_loops, guard_s, loop)
+ return real_loops
+
+def postprocess_loop(loop, loops, memo):
+ if loop in memo:
+ return
+ memo.add(loop)
+ if loop is None:
+ return
+ m = re.search("debug_merge_point\('<code object (.*?)>", loop.content)
+ if m is None:
+ name = '?'
+ else:
+ name = m.group(1)
+ opsno = loop.content.count("\n")
+ lastline = loop.content[loop.content.rfind("\n", 0, len(loop.content) - 2):]
+ m = re.search('descr=<Loop(\d+)', lastline)
+ if m is not None:
+ assert isinstance(loop, FinalBlock)
+ loop.target = loops[int(m.group(1))]
+ bcodes = loop.content.count('debug_merge_point')
+ loop.content = "%s\n%d operations\n%d opcodes" % (name, opsno,
+ bcodes)
+ loop.content += "\n" * (opsno / 100)
+ if bcodes == 0:
+ loop.ratio = opsno
+ else:
+ loop.ratio = float(opsno) / bcodes
+ loop.postprocess(loops, memo)
+
+def postprocess(loops):
+ memo = set()
+ for loop in loops:
+ postprocess_loop(loop, loops, memo)
+
+def main(loopfile):
+ log = logparser.parse_log_file(loopfile)
+ loops = logparser.extract_category(log, "jit-log-opt-")
+ allloops = splitloops(loops)
+ postprocess(allloops)
+ Page(allloops).display()
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser(usage=__doc__)
+ options, args = parser.parse_args(sys.argv)
+ if len(args) != 2:
+ print __doc__
+ sys.exit(1)
+ main(args[1])
Added: pypy/trunk/pypy/jit/tool/test/test_otherviewer.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/jit/tool/test/test_otherviewer.py Mon Feb 22 05:32:47 2010
@@ -0,0 +1,40 @@
+
+from pypy.jit.tool.otherviewer import splitloops, FinalBlock, Block,\
+ split_one_loop, postprocess
+
+def preparse(data):
+ return "\n".join([i.strip() for i in data.split("\n") if i.strip()])
+
+class TestSplitLoops(object):
+ def test_no_of_loops(self):
+ data = [preparse("""
+ # Loop 0 : loop with 39 ops
+ debug_merge_point('')
+ guard_class(p4, 141310752, descr=<Guard5>) [p0, p1]
+ p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_nonnull(p60, descr=<Guard6>) [p0, p1]
+ """), preparse("""
+ # Loop 1 : loop with 46 ops
+ p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ """)]
+ loops = splitloops(data)
+ assert len(loops) == 2
+
+ def test_split_one_loop(self):
+ real_loops = [FinalBlock(preparse("""
+ p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_class(p4, 141310752, descr=<Guard51>) [p0, p1]
+ """), None), FinalBlock(preparse("""
+ p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_nonnull(p60, descr=<Guard5>) [p0, p1]
+ """), None)]
+ split_one_loop(real_loops, 'Guard5', 'extra')
+ assert isinstance(real_loops[1], Block)
+ assert real_loops[1].content.endswith('p1]')
+ assert real_loops[1].left.content == ''
+ assert real_loops[1].right.content.startswith('guard_nonnull')
+
+ def test_postparse(self):
+ real_loops = [FinalBlock("debug_merge_point('<code object _runCallbacks, file '/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357> #40 POP_TOP')", None)]
+ postprocess(real_loops)
+ assert real_loops[0].content.startswith("_runCallbacks, file '/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357")
More information about the Pypy-commit
mailing list