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
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 visitIterable(self, obj, *args, **kwargs):
+ def visitAtom(self, obj):
+ return obj
+
+ 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(newItems)
+ else:
+ return obj
+
+ def visitByteArray(self, obj):
+ return obj
+
+
class Call:
def __init__(self, callTuple):
class Counter(Unpickler):
- def __init__(self, stream, quiet):
+ def __init__(self, stream, verbose = False):
Unpickler.__init__(self, stream)
- self.quiet = quiet
- self.calls = 0
+ self.verbose = verbose
+ self.numCalls = 0
+ self.functionFrequencies = {}
+
+ def parse(self):
+ Unpickler.parse(self)
+
+ functionFrequencies = self.functionFrequencies.items()
+ functionFrequencies.sort(lambda (name1, freq1), (name2, freq2): cmp(freq1, freq2))
+ for name, frequency in functionFrequencies:
+ sys.stdout.write('%8u %s\n' % (frequency, name))
def handleCall(self, call):
- if not self.quiet:
+ if self.verbose:
sys.stdout.write(str(call))
sys.stdout.write('\n')
- self.calls += 1
+ self.numCalls += 1
+ try:
+ self.functionFrequencies[call.functionName] += 1
+ except KeyError:
+ self.functionFrequencies[call.functionName] = 1
def main():
optparser = optparse.OptionParser(
- usage="\n\tapitrace pickle trace. %prog [options]")
+ usage="\n\tapitrace pickle <trace> | %prog [options]")
optparser.add_option(
- '--quiet',
- action="store_true", dest="quiet", default=False,
- help="don't dump calls to stdout")
+ '-p', '--profile',
+ action="store_true", dest="profile", default=False,
+ help="profile call parsing")
+ optparser.add_option(
+ '-v', '--verbose',
+ action="store_true", dest="verbose", default=False,
+ help="dump calls to stdout")
(options, args) = optparser.parse_args(sys.argv[1:])
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
startTime = time.time()
- parser = Counter(sys.stdin, options.quiet)
+ parser = Counter(sys.stdin, options.verbose)
parser.parse()
stopTime = time.time()
duration = stopTime - startTime
- sys.stderr.write('%u calls, %.03f secs, %u calls/sec\n' % (parser.calls, duration, parser.calls/duration))
+
+ if options.profile:
+ sys.stderr.write('Processed %u calls in %.03f secs, at %u calls/sec\n' % (parser.numCalls, duration, parser.numCalls/duration))
if __name__ == '__main__':