Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../usr/lib64/python2....
File: pstats.py
"""Class for printing reports on profiled python code."""
[0] Fix | Delete
[1] Fix | Delete
# Written by James Roskind
[2] Fix | Delete
# Based on prior profile module by Sjoerd Mullender...
[3] Fix | Delete
# which was hacked somewhat by: Guido van Rossum
[4] Fix | Delete
[5] Fix | Delete
# Copyright Disney Enterprises, Inc. All Rights Reserved.
[6] Fix | Delete
# Licensed to PSF under a Contributor Agreement
[7] Fix | Delete
#
[8] Fix | Delete
# Licensed under the Apache License, Version 2.0 (the "License");
[9] Fix | Delete
# you may not use this file except in compliance with the License.
[10] Fix | Delete
# You may obtain a copy of the License at
[11] Fix | Delete
#
[12] Fix | Delete
# http://www.apache.org/licenses/LICENSE-2.0
[13] Fix | Delete
#
[14] Fix | Delete
# Unless required by applicable law or agreed to in writing, software
[15] Fix | Delete
# distributed under the License is distributed on an "AS IS" BASIS,
[16] Fix | Delete
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
[17] Fix | Delete
# either express or implied. See the License for the specific language
[18] Fix | Delete
# governing permissions and limitations under the License.
[19] Fix | Delete
[20] Fix | Delete
[21] Fix | Delete
import sys
[22] Fix | Delete
import os
[23] Fix | Delete
import time
[24] Fix | Delete
import marshal
[25] Fix | Delete
import re
[26] Fix | Delete
from functools import cmp_to_key
[27] Fix | Delete
[28] Fix | Delete
__all__ = ["Stats"]
[29] Fix | Delete
[30] Fix | Delete
class Stats:
[31] Fix | Delete
"""This class is used for creating reports from data generated by the
[32] Fix | Delete
Profile class. It is a "friend" of that class, and imports data either
[33] Fix | Delete
by direct access to members of Profile class, or by reading in a dictionary
[34] Fix | Delete
that was emitted (via marshal) from the Profile class.
[35] Fix | Delete
[36] Fix | Delete
The big change from the previous Profiler (in terms of raw functionality)
[37] Fix | Delete
is that an "add()" method has been provided to combine Stats from
[38] Fix | Delete
several distinct profile runs. Both the constructor and the add()
[39] Fix | Delete
method now take arbitrarily many file names as arguments.
[40] Fix | Delete
[41] Fix | Delete
All the print methods now take an argument that indicates how many lines
[42] Fix | Delete
to print. If the arg is a floating point number between 0 and 1.0, then
[43] Fix | Delete
it is taken as a decimal percentage of the available lines to be printed
[44] Fix | Delete
(e.g., .1 means print 10% of all available lines). If it is an integer,
[45] Fix | Delete
it is taken to mean the number of lines of data that you wish to have
[46] Fix | Delete
printed.
[47] Fix | Delete
[48] Fix | Delete
The sort_stats() method now processes some additional options (i.e., in
[49] Fix | Delete
addition to the old -1, 0, 1, or 2). It takes an arbitrary number of
[50] Fix | Delete
quoted strings to select the sort order. For example sort_stats('time',
[51] Fix | Delete
'name') sorts on the major key of 'internal function time', and on the
[52] Fix | Delete
minor key of 'the name of the function'. Look at the two tables in
[53] Fix | Delete
sort_stats() and get_sort_arg_defs(self) for more examples.
[54] Fix | Delete
[55] Fix | Delete
All methods return self, so you can string together commands like:
[56] Fix | Delete
Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
[57] Fix | Delete
print_stats(5).print_callers(5)
[58] Fix | Delete
"""
[59] Fix | Delete
[60] Fix | Delete
def __init__(self, *args, **kwds):
[61] Fix | Delete
# I can't figure out how to explicitly specify a stream keyword arg
[62] Fix | Delete
# with *args:
[63] Fix | Delete
# def __init__(self, *args, stream=sys.stdout): ...
[64] Fix | Delete
# so I use **kwds and sqauwk if something unexpected is passed in.
[65] Fix | Delete
self.stream = sys.stdout
[66] Fix | Delete
if "stream" in kwds:
[67] Fix | Delete
self.stream = kwds["stream"]
[68] Fix | Delete
del kwds["stream"]
[69] Fix | Delete
if kwds:
[70] Fix | Delete
keys = kwds.keys()
[71] Fix | Delete
keys.sort()
[72] Fix | Delete
extras = ", ".join(["%s=%s" % (k, kwds[k]) for k in keys])
[73] Fix | Delete
raise ValueError, "unrecognized keyword args: %s" % extras
[74] Fix | Delete
if not len(args):
[75] Fix | Delete
arg = None
[76] Fix | Delete
else:
[77] Fix | Delete
arg = args[0]
[78] Fix | Delete
args = args[1:]
[79] Fix | Delete
self.init(arg)
[80] Fix | Delete
self.add(*args)
[81] Fix | Delete
[82] Fix | Delete
def init(self, arg):
[83] Fix | Delete
self.all_callees = None # calc only if needed
[84] Fix | Delete
self.files = []
[85] Fix | Delete
self.fcn_list = None
[86] Fix | Delete
self.total_tt = 0
[87] Fix | Delete
self.total_calls = 0
[88] Fix | Delete
self.prim_calls = 0
[89] Fix | Delete
self.max_name_len = 0
[90] Fix | Delete
self.top_level = {}
[91] Fix | Delete
self.stats = {}
[92] Fix | Delete
self.sort_arg_dict = {}
[93] Fix | Delete
self.load_stats(arg)
[94] Fix | Delete
trouble = 1
[95] Fix | Delete
try:
[96] Fix | Delete
self.get_top_level_stats()
[97] Fix | Delete
trouble = 0
[98] Fix | Delete
finally:
[99] Fix | Delete
if trouble:
[100] Fix | Delete
print >> self.stream, "Invalid timing data",
[101] Fix | Delete
if self.files: print >> self.stream, self.files[-1],
[102] Fix | Delete
print >> self.stream
[103] Fix | Delete
[104] Fix | Delete
def load_stats(self, arg):
[105] Fix | Delete
if not arg: self.stats = {}
[106] Fix | Delete
elif isinstance(arg, basestring):
[107] Fix | Delete
f = open(arg, 'rb')
[108] Fix | Delete
self.stats = marshal.load(f)
[109] Fix | Delete
f.close()
[110] Fix | Delete
try:
[111] Fix | Delete
file_stats = os.stat(arg)
[112] Fix | Delete
arg = time.ctime(file_stats.st_mtime) + " " + arg
[113] Fix | Delete
except: # in case this is not unix
[114] Fix | Delete
pass
[115] Fix | Delete
self.files = [ arg ]
[116] Fix | Delete
elif hasattr(arg, 'create_stats'):
[117] Fix | Delete
arg.create_stats()
[118] Fix | Delete
self.stats = arg.stats
[119] Fix | Delete
arg.stats = {}
[120] Fix | Delete
if not self.stats:
[121] Fix | Delete
raise TypeError("Cannot create or construct a %r object from %r"
[122] Fix | Delete
% (self.__class__, arg))
[123] Fix | Delete
return
[124] Fix | Delete
[125] Fix | Delete
def get_top_level_stats(self):
[126] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.items():
[127] Fix | Delete
self.total_calls += nc
[128] Fix | Delete
self.prim_calls += cc
[129] Fix | Delete
self.total_tt += tt
[130] Fix | Delete
if ("jprofile", 0, "profiler") in callers:
[131] Fix | Delete
self.top_level[func] = None
[132] Fix | Delete
if len(func_std_string(func)) > self.max_name_len:
[133] Fix | Delete
self.max_name_len = len(func_std_string(func))
[134] Fix | Delete
[135] Fix | Delete
def add(self, *arg_list):
[136] Fix | Delete
if not arg_list: return self
[137] Fix | Delete
if len(arg_list) > 1: self.add(*arg_list[1:])
[138] Fix | Delete
other = arg_list[0]
[139] Fix | Delete
if type(self) != type(other) or self.__class__ != other.__class__:
[140] Fix | Delete
other = Stats(other)
[141] Fix | Delete
self.files += other.files
[142] Fix | Delete
self.total_calls += other.total_calls
[143] Fix | Delete
self.prim_calls += other.prim_calls
[144] Fix | Delete
self.total_tt += other.total_tt
[145] Fix | Delete
for func in other.top_level:
[146] Fix | Delete
self.top_level[func] = None
[147] Fix | Delete
[148] Fix | Delete
if self.max_name_len < other.max_name_len:
[149] Fix | Delete
self.max_name_len = other.max_name_len
[150] Fix | Delete
[151] Fix | Delete
self.fcn_list = None
[152] Fix | Delete
[153] Fix | Delete
for func, stat in other.stats.iteritems():
[154] Fix | Delete
if func in self.stats:
[155] Fix | Delete
old_func_stat = self.stats[func]
[156] Fix | Delete
else:
[157] Fix | Delete
old_func_stat = (0, 0, 0, 0, {},)
[158] Fix | Delete
self.stats[func] = add_func_stats(old_func_stat, stat)
[159] Fix | Delete
return self
[160] Fix | Delete
[161] Fix | Delete
def dump_stats(self, filename):
[162] Fix | Delete
"""Write the profile data to a file we know how to load back."""
[163] Fix | Delete
f = file(filename, 'wb')
[164] Fix | Delete
try:
[165] Fix | Delete
marshal.dump(self.stats, f)
[166] Fix | Delete
finally:
[167] Fix | Delete
f.close()
[168] Fix | Delete
[169] Fix | Delete
# list the tuple indices and directions for sorting,
[170] Fix | Delete
# along with some printable description
[171] Fix | Delete
sort_arg_dict_default = {
[172] Fix | Delete
"calls" : (((1,-1), ), "call count"),
[173] Fix | Delete
"ncalls" : (((1,-1), ), "call count"),
[174] Fix | Delete
"cumtime" : (((3,-1), ), "cumulative time"),
[175] Fix | Delete
"cumulative": (((3,-1), ), "cumulative time"),
[176] Fix | Delete
"file" : (((4, 1), ), "file name"),
[177] Fix | Delete
"filename" : (((4, 1), ), "file name"),
[178] Fix | Delete
"line" : (((5, 1), ), "line number"),
[179] Fix | Delete
"module" : (((4, 1), ), "file name"),
[180] Fix | Delete
"name" : (((6, 1), ), "function name"),
[181] Fix | Delete
"nfl" : (((6, 1),(4, 1),(5, 1),), "name/file/line"),
[182] Fix | Delete
"pcalls" : (((0,-1), ), "primitive call count"),
[183] Fix | Delete
"stdname" : (((7, 1), ), "standard name"),
[184] Fix | Delete
"time" : (((2,-1), ), "internal time"),
[185] Fix | Delete
"tottime" : (((2,-1), ), "internal time"),
[186] Fix | Delete
}
[187] Fix | Delete
[188] Fix | Delete
def get_sort_arg_defs(self):
[189] Fix | Delete
"""Expand all abbreviations that are unique."""
[190] Fix | Delete
if not self.sort_arg_dict:
[191] Fix | Delete
self.sort_arg_dict = dict = {}
[192] Fix | Delete
bad_list = {}
[193] Fix | Delete
for word, tup in self.sort_arg_dict_default.iteritems():
[194] Fix | Delete
fragment = word
[195] Fix | Delete
while fragment:
[196] Fix | Delete
if not fragment:
[197] Fix | Delete
break
[198] Fix | Delete
if fragment in dict:
[199] Fix | Delete
bad_list[fragment] = 0
[200] Fix | Delete
break
[201] Fix | Delete
dict[fragment] = tup
[202] Fix | Delete
fragment = fragment[:-1]
[203] Fix | Delete
for word in bad_list:
[204] Fix | Delete
del dict[word]
[205] Fix | Delete
return self.sort_arg_dict
[206] Fix | Delete
[207] Fix | Delete
def sort_stats(self, *field):
[208] Fix | Delete
if not field:
[209] Fix | Delete
self.fcn_list = 0
[210] Fix | Delete
return self
[211] Fix | Delete
if len(field) == 1 and isinstance(field[0], (int, long)):
[212] Fix | Delete
# Be compatible with old profiler
[213] Fix | Delete
field = [ {-1: "stdname",
[214] Fix | Delete
0: "calls",
[215] Fix | Delete
1: "time",
[216] Fix | Delete
2: "cumulative"}[field[0]] ]
[217] Fix | Delete
[218] Fix | Delete
sort_arg_defs = self.get_sort_arg_defs()
[219] Fix | Delete
sort_tuple = ()
[220] Fix | Delete
self.sort_type = ""
[221] Fix | Delete
connector = ""
[222] Fix | Delete
for word in field:
[223] Fix | Delete
sort_tuple = sort_tuple + sort_arg_defs[word][0]
[224] Fix | Delete
self.sort_type += connector + sort_arg_defs[word][1]
[225] Fix | Delete
connector = ", "
[226] Fix | Delete
[227] Fix | Delete
stats_list = []
[228] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.iteritems():
[229] Fix | Delete
stats_list.append((cc, nc, tt, ct) + func +
[230] Fix | Delete
(func_std_string(func), func))
[231] Fix | Delete
[232] Fix | Delete
stats_list.sort(key=cmp_to_key(TupleComp(sort_tuple).compare))
[233] Fix | Delete
[234] Fix | Delete
self.fcn_list = fcn_list = []
[235] Fix | Delete
for tuple in stats_list:
[236] Fix | Delete
fcn_list.append(tuple[-1])
[237] Fix | Delete
return self
[238] Fix | Delete
[239] Fix | Delete
def reverse_order(self):
[240] Fix | Delete
if self.fcn_list:
[241] Fix | Delete
self.fcn_list.reverse()
[242] Fix | Delete
return self
[243] Fix | Delete
[244] Fix | Delete
def strip_dirs(self):
[245] Fix | Delete
oldstats = self.stats
[246] Fix | Delete
self.stats = newstats = {}
[247] Fix | Delete
max_name_len = 0
[248] Fix | Delete
for func, (cc, nc, tt, ct, callers) in oldstats.iteritems():
[249] Fix | Delete
newfunc = func_strip_path(func)
[250] Fix | Delete
if len(func_std_string(newfunc)) > max_name_len:
[251] Fix | Delete
max_name_len = len(func_std_string(newfunc))
[252] Fix | Delete
newcallers = {}
[253] Fix | Delete
for func2, caller in callers.iteritems():
[254] Fix | Delete
newcallers[func_strip_path(func2)] = caller
[255] Fix | Delete
[256] Fix | Delete
if newfunc in newstats:
[257] Fix | Delete
newstats[newfunc] = add_func_stats(
[258] Fix | Delete
newstats[newfunc],
[259] Fix | Delete
(cc, nc, tt, ct, newcallers))
[260] Fix | Delete
else:
[261] Fix | Delete
newstats[newfunc] = (cc, nc, tt, ct, newcallers)
[262] Fix | Delete
old_top = self.top_level
[263] Fix | Delete
self.top_level = new_top = {}
[264] Fix | Delete
for func in old_top:
[265] Fix | Delete
new_top[func_strip_path(func)] = None
[266] Fix | Delete
[267] Fix | Delete
self.max_name_len = max_name_len
[268] Fix | Delete
[269] Fix | Delete
self.fcn_list = None
[270] Fix | Delete
self.all_callees = None
[271] Fix | Delete
return self
[272] Fix | Delete
[273] Fix | Delete
def calc_callees(self):
[274] Fix | Delete
if self.all_callees: return
[275] Fix | Delete
self.all_callees = all_callees = {}
[276] Fix | Delete
for func, (cc, nc, tt, ct, callers) in self.stats.iteritems():
[277] Fix | Delete
if not func in all_callees:
[278] Fix | Delete
all_callees[func] = {}
[279] Fix | Delete
for func2, caller in callers.iteritems():
[280] Fix | Delete
if not func2 in all_callees:
[281] Fix | Delete
all_callees[func2] = {}
[282] Fix | Delete
all_callees[func2][func] = caller
[283] Fix | Delete
return
[284] Fix | Delete
[285] Fix | Delete
#******************************************************************
[286] Fix | Delete
# The following functions support actual printing of reports
[287] Fix | Delete
#******************************************************************
[288] Fix | Delete
[289] Fix | Delete
# Optional "amount" is either a line count, or a percentage of lines.
[290] Fix | Delete
[291] Fix | Delete
def eval_print_amount(self, sel, list, msg):
[292] Fix | Delete
new_list = list
[293] Fix | Delete
if isinstance(sel, basestring):
[294] Fix | Delete
try:
[295] Fix | Delete
rex = re.compile(sel)
[296] Fix | Delete
except re.error:
[297] Fix | Delete
msg += " <Invalid regular expression %r>\n" % sel
[298] Fix | Delete
return new_list, msg
[299] Fix | Delete
new_list = []
[300] Fix | Delete
for func in list:
[301] Fix | Delete
if rex.search(func_std_string(func)):
[302] Fix | Delete
new_list.append(func)
[303] Fix | Delete
else:
[304] Fix | Delete
count = len(list)
[305] Fix | Delete
if isinstance(sel, float) and 0.0 <= sel < 1.0:
[306] Fix | Delete
count = int(count * sel + .5)
[307] Fix | Delete
new_list = list[:count]
[308] Fix | Delete
elif isinstance(sel, (int, long)) and 0 <= sel < count:
[309] Fix | Delete
count = sel
[310] Fix | Delete
new_list = list[:count]
[311] Fix | Delete
if len(list) != len(new_list):
[312] Fix | Delete
msg += " List reduced from %r to %r due to restriction <%r>\n" % (
[313] Fix | Delete
len(list), len(new_list), sel)
[314] Fix | Delete
[315] Fix | Delete
return new_list, msg
[316] Fix | Delete
[317] Fix | Delete
def get_print_list(self, sel_list):
[318] Fix | Delete
width = self.max_name_len
[319] Fix | Delete
if self.fcn_list:
[320] Fix | Delete
stat_list = self.fcn_list[:]
[321] Fix | Delete
msg = " Ordered by: " + self.sort_type + '\n'
[322] Fix | Delete
else:
[323] Fix | Delete
stat_list = self.stats.keys()
[324] Fix | Delete
msg = " Random listing order was used\n"
[325] Fix | Delete
[326] Fix | Delete
for selection in sel_list:
[327] Fix | Delete
stat_list, msg = self.eval_print_amount(selection, stat_list, msg)
[328] Fix | Delete
[329] Fix | Delete
count = len(stat_list)
[330] Fix | Delete
[331] Fix | Delete
if not stat_list:
[332] Fix | Delete
return 0, stat_list
[333] Fix | Delete
print >> self.stream, msg
[334] Fix | Delete
if count < len(self.stats):
[335] Fix | Delete
width = 0
[336] Fix | Delete
for func in stat_list:
[337] Fix | Delete
if len(func_std_string(func)) > width:
[338] Fix | Delete
width = len(func_std_string(func))
[339] Fix | Delete
return width+2, stat_list
[340] Fix | Delete
[341] Fix | Delete
def print_stats(self, *amount):
[342] Fix | Delete
for filename in self.files:
[343] Fix | Delete
print >> self.stream, filename
[344] Fix | Delete
if self.files: print >> self.stream
[345] Fix | Delete
indent = ' ' * 8
[346] Fix | Delete
for func in self.top_level:
[347] Fix | Delete
print >> self.stream, indent, func_get_function_name(func)
[348] Fix | Delete
[349] Fix | Delete
print >> self.stream, indent, self.total_calls, "function calls",
[350] Fix | Delete
if self.total_calls != self.prim_calls:
[351] Fix | Delete
print >> self.stream, "(%d primitive calls)" % self.prim_calls,
[352] Fix | Delete
print >> self.stream, "in %.3f seconds" % self.total_tt
[353] Fix | Delete
print >> self.stream
[354] Fix | Delete
width, list = self.get_print_list(amount)
[355] Fix | Delete
if list:
[356] Fix | Delete
self.print_title()
[357] Fix | Delete
for func in list:
[358] Fix | Delete
self.print_line(func)
[359] Fix | Delete
print >> self.stream
[360] Fix | Delete
print >> self.stream
[361] Fix | Delete
return self
[362] Fix | Delete
[363] Fix | Delete
def print_callees(self, *amount):
[364] Fix | Delete
width, list = self.get_print_list(amount)
[365] Fix | Delete
if list:
[366] Fix | Delete
self.calc_callees()
[367] Fix | Delete
[368] Fix | Delete
self.print_call_heading(width, "called...")
[369] Fix | Delete
for func in list:
[370] Fix | Delete
if func in self.all_callees:
[371] Fix | Delete
self.print_call_line(width, func, self.all_callees[func])
[372] Fix | Delete
else:
[373] Fix | Delete
self.print_call_line(width, func, {})
[374] Fix | Delete
print >> self.stream
[375] Fix | Delete
print >> self.stream
[376] Fix | Delete
return self
[377] Fix | Delete
[378] Fix | Delete
def print_callers(self, *amount):
[379] Fix | Delete
width, list = self.get_print_list(amount)
[380] Fix | Delete
if list:
[381] Fix | Delete
self.print_call_heading(width, "was called by...")
[382] Fix | Delete
for func in list:
[383] Fix | Delete
cc, nc, tt, ct, callers = self.stats[func]
[384] Fix | Delete
self.print_call_line(width, func, callers, "<-")
[385] Fix | Delete
print >> self.stream
[386] Fix | Delete
print >> self.stream
[387] Fix | Delete
return self
[388] Fix | Delete
[389] Fix | Delete
def print_call_heading(self, name_size, column_title):
[390] Fix | Delete
print >> self.stream, "Function ".ljust(name_size) + column_title
[391] Fix | Delete
# print sub-header only if we have new-style callers
[392] Fix | Delete
subheader = False
[393] Fix | Delete
for cc, nc, tt, ct, callers in self.stats.itervalues():
[394] Fix | Delete
if callers:
[395] Fix | Delete
value = callers.itervalues().next()
[396] Fix | Delete
subheader = isinstance(value, tuple)
[397] Fix | Delete
break
[398] Fix | Delete
if subheader:
[399] Fix | Delete
print >> self.stream, " "*name_size + " ncalls tottime cumtime"
[400] Fix | Delete
[401] Fix | Delete
def print_call_line(self, name_size, source, call_dict, arrow="->"):
[402] Fix | Delete
print >> self.stream, func_std_string(source).ljust(name_size) + arrow,
[403] Fix | Delete
if not call_dict:
[404] Fix | Delete
print >> self.stream
[405] Fix | Delete
return
[406] Fix | Delete
clist = call_dict.keys()
[407] Fix | Delete
clist.sort()
[408] Fix | Delete
indent = ""
[409] Fix | Delete
for func in clist:
[410] Fix | Delete
name = func_std_string(func)
[411] Fix | Delete
value = call_dict[func]
[412] Fix | Delete
if isinstance(value, tuple):
[413] Fix | Delete
nc, cc, tt, ct = value
[414] Fix | Delete
if nc != cc:
[415] Fix | Delete
substats = '%d/%d' % (nc, cc)
[416] Fix | Delete
else:
[417] Fix | Delete
substats = '%d' % (nc,)
[418] Fix | Delete
substats = '%s %s %s %s' % (substats.rjust(7+2*len(indent)),
[419] Fix | Delete
f8(tt), f8(ct), name)
[420] Fix | Delete
left_width = name_size + 1
[421] Fix | Delete
else:
[422] Fix | Delete
substats = '%s(%r) %s' % (name, value, f8(self.stats[func][3]))
[423] Fix | Delete
left_width = name_size + 3
[424] Fix | Delete
print >> self.stream, indent*left_width + substats
[425] Fix | Delete
indent = " "
[426] Fix | Delete
[427] Fix | Delete
def print_title(self):
[428] Fix | Delete
print >> self.stream, ' ncalls tottime percall cumtime percall',
[429] Fix | Delete
print >> self.stream, 'filename:lineno(function)'
[430] Fix | Delete
[431] Fix | Delete
def print_line(self, func): # hack : should print percentages
[432] Fix | Delete
cc, nc, tt, ct, callers = self.stats[func]
[433] Fix | Delete
c = str(nc)
[434] Fix | Delete
if nc != cc:
[435] Fix | Delete
c = c + '/' + str(cc)
[436] Fix | Delete
print >> self.stream, c.rjust(9),
[437] Fix | Delete
print >> self.stream, f8(tt),
[438] Fix | Delete
if nc == 0:
[439] Fix | Delete
print >> self.stream, ' '*8,
[440] Fix | Delete
else:
[441] Fix | Delete
print >> self.stream, f8(float(tt)/nc),
[442] Fix | Delete
print >> self.stream, f8(ct),
[443] Fix | Delete
if cc == 0:
[444] Fix | Delete
print >> self.stream, ' '*8,
[445] Fix | Delete
else:
[446] Fix | Delete
print >> self.stream, f8(float(ct)/cc),
[447] Fix | Delete
print >> self.stream, func_std_string(func)
[448] Fix | Delete
[449] Fix | Delete
class TupleComp:
[450] Fix | Delete
"""This class provides a generic function for comparing any two tuples.
[451] Fix | Delete
Each instance records a list of tuple-indices (from most significant
[452] Fix | Delete
to least significant), and sort direction (ascending or decending) for
[453] Fix | Delete
each tuple-index. The compare functions can then be used as the function
[454] Fix | Delete
argument to the system sort() function when a list of tuples need to be
[455] Fix | Delete
sorted in the instances order."""
[456] Fix | Delete
[457] Fix | Delete
def __init__(self, comp_select_list):
[458] Fix | Delete
self.comp_select_list = comp_select_list
[459] Fix | Delete
[460] Fix | Delete
def compare (self, left, right):
[461] Fix | Delete
for index, direction in self.comp_select_list:
[462] Fix | Delete
l = left[index]
[463] Fix | Delete
r = right[index]
[464] Fix | Delete
if l < r:
[465] Fix | Delete
return -direction
[466] Fix | Delete
if l > r:
[467] Fix | Delete
return direction
[468] Fix | Delete
return 0
[469] Fix | Delete
[470] Fix | Delete
#**************************************************************************
[471] Fix | Delete
# func_name is a triple (file:string, line:int, name:string)
[472] Fix | Delete
[473] Fix | Delete
def func_strip_path(func_name):
[474] Fix | Delete
filename, line, name = func_name
[475] Fix | Delete
return os.path.basename(filename), line, name
[476] Fix | Delete
[477] Fix | Delete
def func_get_function_name(func):
[478] Fix | Delete
return func[2]
[479] Fix | Delete
[480] Fix | Delete
def func_std_string(func_name): # match what old profile produced
[481] Fix | Delete
if func_name[:2] == ('~', 0):
[482] Fix | Delete
# special case for built-in functions
[483] Fix | Delete
name = func_name[2]
[484] Fix | Delete
if name.startswith('<') and name.endswith('>'):
[485] Fix | Delete
return '{%s}' % name[1:-1]
[486] Fix | Delete
else:
[487] Fix | Delete
return name
[488] Fix | Delete
else:
[489] Fix | Delete
return "%s:%d(%s)" % func_name
[490] Fix | Delete
[491] Fix | Delete
#**************************************************************************
[492] Fix | Delete
# The following functions combine statists for pairs functions.
[493] Fix | Delete
# The bulk of the processing involves correctly handling "call" lists,
[494] Fix | Delete
# such as callers and callees.
[495] Fix | Delete
#**************************************************************************
[496] Fix | Delete
[497] Fix | Delete
def add_func_stats(target, source):
[498] Fix | Delete
"""Add together all the stats for two profile entries."""
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function