]> git.cworth.org Git - apitrace/commitdiff
Optimize tracediff2.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sat, 17 Mar 2012 21:07:02 +0000 (21:07 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Sat, 17 Mar 2012 21:07:02 +0000 (21:07 +0000)
scripts/tracediff2.py
scripts/unpickle.py

index 3f14d36d2410f204594b922e2bb08d96b0ab749b..d6fd39261228b5adb1a391263e7b495f4d086e95 100755 (executable)
@@ -32,7 +32,7 @@ import os.path
 import subprocess
 import sys
 
-from unpickle import Unpickler, Dumper
+from unpickle import Unpickler, Dumper, Rebuilder
 from highlight import ColorHighlighter, LessHighlighter
 
 
@@ -46,16 +46,45 @@ ignoredFunctionNames = set([
 ])
 
 
+class Blob:
+    '''Data-less proxy for bytearrays, to save memory.'''
+
+    def __init__(self, size, hash):
+        self.size = size
+        self.hash = hash
+
+    def __repr__(self):
+        return 'blob(%u)' % self.size
+
+    def __eq__(self, other):
+        return self.size == other.size and self.hash == other.hash
+
+    def __hash__(self):
+        return self.hash
+
+
+class BlobReplacer(Rebuilder):
+    '''Replace blobs with proxys.'''
+
+    def visitByteArray(self, obj):
+        return Blob(len(obj), hash(str(obj)))
+
+    def visitCall(self, call):
+        call.args = map(self.visit, call.args)
+        call.ret = self.visit(call.ret)
+
+
 class Loader(Unpickler):
 
     def __init__(self, stream):
         Unpickler.__init__(self, stream)
         self.calls = []
+        self.rebuilder = BlobReplacer()
 
     def handleCall(self, call):
         if call.functionName not in ignoredFunctionNames:
+            self.rebuilder.visitCall(call)
             self.calls.append(call)
-            hash(call)
 
 
 def readtrace(trace, calls):
@@ -258,7 +287,7 @@ def main():
         help='apitrace command [default: %default]')
     optparser.add_option(
         '-c', '--calls', metavar='CALLSET',
-        type="string", dest="calls", default='1-10000',
+        type="string", dest="calls", default='*',
         help="calls to compare [default: %default]")
     optparser.add_option(
         '--ref-calls', metavar='CALLSET',
@@ -292,7 +321,10 @@ def main():
         highlighter = ColorHighlighter()
 
     differ = SDiffer(ref_calls, src_calls, highlighter, options.call_nos)
-    differ.diff()
+    try:
+        differ.diff()
+    except IOError:
+        pass
 
 
 if __name__ == '__main__':
index 3f0bc42fc34ce6c1b01a9128ddaddeda754d9ab1..ab2dc4db0311292dce0a0a8ab23474cdc3d9b300 100755 (executable)
@@ -56,40 +56,44 @@ class Visitor:
         self.dispatch[dict] = self.visitDict
         self.dispatch[bytearray] = self.visitByteArray
 
-    def visit(self, obj, *args, **kwargs):
-        return self.dispatch[type(obj)](obj, *args, **kwargs)
+    def visit(self, obj):
+        method = self.dispatch.get(type(obj), self.visitObj)
+        return method(obj)
 
-    def visitAtom(self, obj, *args, **kwargs):
+    def visitObj(self, obj):
         raise NotImplementedError
 
-    def visitNone(self, obj, *args, **kwargs):
-        return self.visitAtom(obj, *args, **kwargs)
+    def visitAtom(self, obj):
+        return self.visitObj(obj)
 
-    def visitBool(self, obj, *args, **kwargs):
-        return self.visitAtom(obj, *args, **kwargs)
+    def visitNone(self, obj):
+        return self.visitAtom(obj)
 
-    def visitInt(self, obj, *args, **kwargs):
-        return self.visitAtom(obj, *args, **kwargs)
+    def visitBool(self, obj):
+        return self.visitAtom(obj)
 
-    def visitFloat(self, obj, *args, **kwargs):
-        return self.visitAtom(obj, *args, **kwargs)
+    def visitInt(self, obj):
+        return self.visitAtom(obj)
 
-    def visitStr(self, obj, *args, **kwargs):
-        return self.visitAtom(obj, *args, **kwargs)
+    def visitFloat(self, obj):
+        return self.visitAtom(obj)
 
-    def visitIterable(self, obj, *args, **kwargs):
-        raise NotImplementedError
+    def visitStr(self, obj):
+        return self.visitAtom(obj)
+
+    def visitIterable(self, obj):
+        return self.visitObj(obj)
 
-    def visitTuple(self, obj, *args, **kwargs):
-        return self.visitIterable(obj, *args, **kwargs)
+    def visitTuple(self, obj):
+        return self.visitIterable(obj)
 
-    def visitList(self, obj, *args, **kwargs):
-        return self.visitIterable(obj, *args, **kwargs)
+    def visitList(self, obj):
+        return self.visitIterable(obj)
 
-    def visitDict(self, obj, *args, **kwargs):
+    def visitDict(self, obj):
         raise NotImplementedError
 
-    def visitByteArray(self, obj, *args, **kwargs):
+    def visitByteArray(self, obj):
         raise NotImplementedError
 
 
@@ -97,38 +101,65 @@ class Dumper(Visitor):
 
     id_re = re.compile('^[_A-Za-z][_A-Za-z0-9]*$')
 
-    def visitAtom(self, obj, *args, **kwargs):
+    def visitObj(self, obj):
         return repr(obj)
 
-    def visitStr(self, obj, *args, **kwargs):
+    def visitStr(self, obj):
         if self.id_re.match(obj):
             return obj
         else:
             return repr(obj)
 
-    def visitTuple(self, obj, *args, **kwargs):
+    def visitTuple(self, obj):
         return '[' + ', '.join(itertools.imap(self.visit, obj)) + ']'
 
-    def visitList(self, obj, *args, **kwargs):
+    def visitList(self, obj):
         return '(' + ', '.join(itertools.imap(self.visit, obj)) + ')'
 
-    def visitByteArray(self, obj, *args, **kwargs):
+    def visitByteArray(self, obj):
         return 'blob(%u)' % len(obj)
 
 
 class Hasher(Visitor):
     '''Returns a hashable version of the objtree.'''
 
-    def visitAtom(self, obj, *args, **kwargs):
+    def visitObj(self, obj):
+        return obj
+
+    def visitAtom(self, obj):
         return obj
 
-    def visitIterable(self, obj, *args, **kwargs):
+    def visitIterable(self, obj):
         return tuple(itertools.imap(self.visit, obj))
 
-    def visitByteArray(self, obj, *args, **kwargs):
+    def visitByteArray(self, obj):
         return str(obj)
 
 
+class Rebuilder(Visitor):
+    '''Returns a hashable version of the objtree.'''
+
+    def visitAtom(self, obj):
+        return obj
+
+    def visitIterable(self, obj):
+        changed = False
+        newItems = []
+        for oldItem in obj:
+            newItem = self.visit(oldItem)
+            if newItem is not oldItem:
+                changed = True
+            newItems.append(newItem)
+        if changed:
+            klass = type(obj)
+            return klass(changed)
+        else:
+            return obj
+
+    def visitByteArray(self, obj):
+        return obj
+
+
 class Call:
 
     def __init__(self, callTuple):
@@ -203,7 +234,7 @@ def main():
     optparser = optparse.OptionParser(
         usage="\n\tapitrace pickle trace. %prog [options]")
     optparser.add_option(
-        '--quiet',
+        '-q', '--quiet',
         action="store_true", dest="quiet", default=False,
         help="don't dump calls to stdout")