# -*- Mode: Python -*- import os import re # 08135174 00000041 T PyRun_SimpleString fun_re = re.compile ('([0-9a-f]+) ([0-9a-f]+) [Tt] ([0-9A-Za-z_]+)\n') def get_syms (path_exe): p = os.popen ('nm -S %s' % (path_exe,), 'r') d = {} while 1: line = p.readline() if not line: break else: probe = fun_re.match (line) if probe is not None: addr, size, name = probe.groups() d[int(addr,16)] = (name, int(size,16)) return d def get_sym (syms, addr): if syms.has_key (addr): return syms[addr][0] else: return hex(addr) def read_profile (path_prof): graph = {} f = open (path_prof, 'rb') while 1: line = f.readline() if not line or line[0] == '-': break else: addr, count, ticks = line.split() addr = int (addr, 16) count = int (count) ticks = int (ticks) graph[addr] = (count, ticks, []) line = f.readline() while 1: # read fun address if not line: break else: caller = int(line,16) callees = graph[caller][2] while 1: line = f.readline() if not line: break elif line[0] == ' ': addr, count = line.split() addr = int(addr, 16) count = int (count) callees.append ((addr, count)) else: break return graph def print_profile (syms, graph, sortby='ticks'): # pull out ticks and counts profile = [(t, c, a) for (a, (c, t, ignore)) in graph.iteritems()] # convert addresses to names profile = [(t, c, get_sym(syms,a)) for (t, c, a) in profile] # repair zero-count entries profile = [(t, c or 1, n) for (t,c,n) in profile] # synthesize ticks/call profile = [(t, c, t/c, n) for (t,c,n) in profile] which = {'ticks':0, 'count':1, 'tpc':2, 'name':3}[sortby] profile.sort (lambda a,b: cmp(a[which],b[which])) sum_ticks = 0 sum_calls = 0 for ticks, count, per, name in profile: sum_ticks += ticks sum_calls += count sum_percent = 0 for ticks, count, per, name in profile: percent = 100 * (ticks / float(sum_ticks)) print '%15d %6.2f %12d %10d %s' % ( ticks, percent, count, per, name ) sum_percent += percent print '%15d %6.2f %12d %10s (totals)' % ( sum_ticks, sum_percent, sum_calls, '' ) def print_graph (syms, graph): # we have the forward graph, build the reverse from it rg = {} for addr, (total_count, ticks, callees) in graph.iteritems(): for callee, count in callees: if rg.has_key (callee): rg[callee].append ((addr, count)) else: rg[callee] = [(addr, count)] # gi = graph.items() gi.sort() for addr, (total_count, ticks, callees) in gi: print '------------------------------' if rg.has_key (addr): for caller, count in rg[addr]: print ' %8s %8d %s' % ('', count, get_sym (syms, caller)) print '%8d %s' % (total_count, get_sym (syms, addr)) for callee, count in callees: if (callee == addr): print ' %8s %8d [recursive]' % ('', count,) else: print ' %8s %8d %s' % ('', count, get_sym (syms, callee)) def print_profile_html (syms, graph): # pull out ticks and counts profile = [(t, c, a) for (a, (c, t, ignore)) in graph.iteritems()] # convert addresses to names profile = [(t, c, get_sym(syms,a)) for (t, c, a) in profile] # repair zero-count entries profile = [(t, c or 1, n) for (t,c,n) in profile] # synthesize ticks/call profile = [(t, c, t/c, n) for (t,c,n) in profile] # sortby == ticks which = 0 profile.sort (lambda a,b: cmp(b[which],a[which])) sum_ticks = 0 sum_calls = 0 for ticks, count, per, name in profile: sum_ticks += ticks sum_calls += count print '
ticks | percent | calls | ticks/call | function | ' i = 0 for ticks, count, per, name in profile: percent = 100 * (ticks / float(sum_ticks)) print ( '
---|---|---|---|---|
%d | ' '%6.2f | ' '%d | ' '%d | ' '%s | ' '
%d | %6.2f | %d | (totals) |
' if rg.has_key (addr): l = [] for caller, count in rg[addr]: cname = get_sym (syms, caller) tc, tt, cl = graph[addr] est_ticks = (ticks * count) / total_count l.append ((count, tc, est_ticks, cname)) l.sort (lambda a,b:cmp(a[2],b[2])) for count, tc, est_ticks, cname in l: print '%10d/%-10d %15d %s' % (count, tc, est_ticks, cname, cname) print '%15d %15d %s' % (total_count, ticks, name) callees2 = [] for callee, count in callees: cname = get_sym (syms, callee) tc, tt, cl = graph[callee] est_ticks = (tt / tc) * count callees2.append ((count, tc, est_ticks, cname)) # sort by estimated ticks callees2.sort (lambda a,b: cmp (b[2], a[2])) for count, tc, est_ticks, cname in callees2: print '%10d/%-10d %15d %s' % (count, tc, est_ticks, cname, cname) print '' def print_html (syms, graph): print '