in utils/ptreetime/ptreetime.py [0:0]
def action_analyze(name, args):
"""analyze a ptreetime data file"""
parser = optparse.OptionParser("""\
usage: %%prog %(name)s [options] <path>
Execute the given command and track the execution time of all the processes
which are created during the execution.""" % locals())
parser.add_option("-f", "--focus", dest="focus",
help="focus on the given process name",
action="store", default=None)
parser.add_option("--show-tree", dest="show_tree",
help="Print the entire call tree",
action="store_true")
parser.add_option("", "--gen-report", dest="lnt_report_path",
help="generate an LNT report",
action="store", default=None)
parser.add_option("", "--report-machine", dest="report_machine",
help="machine name to include in the LNT report",
action="store", default=None)
parser.add_option("", "--report-run-order", dest="report_run_order",
help="run order to include in the LNT report",
action="store", default=None)
parser.add_option("", "--report-sub-arg", dest="report_sub_args",
help="add an argument replacement pattern",
metavar="PATTERN=REPLACEMENT",
action="append", default=[])
(opts, args) = parser.parse_args(args)
if len(args) < 1:
parser.error("invalid number of arguments")
if opts.lnt_report_path:
if opts.report_machine is None:
parser.error("--report-machine is required with --gen-report")
if opts.report_run_order is None:
parser.error("--report-run-order is required with --gen-report")
else:
if opts.report_machine is not None:
parser.error("--report-machine is unused without --gen-report")
if opts.report_run_order is not None:
parser.error("--report-run-order is unused without --gen-report")
if opts.report_sub_args:
parser.error("--report-sub-arg is unused without --gen-report")
paths = args
def find_focused_roots(node):
# If this is a focused node, add it to the list.
if opts.focus is None or node.name == opts.focus:
focused_roots.append(node)
return
# Otherwise, recurse on each child.
for child in node.children:
find_focused_roots(child)
focused_roots = []
for path in paths:
# Load each file.
target_root,roots,active_processes = _parse_event_log(path)
find_focused_roots(target_root)
# For each root, show the flattened performance.
def print_node(node, depth):
# If this node isn't complete, ignore it.
if node.start_timestamp is None:
warning("ignoring incomplete node %r (didn't see create)" % (
(node.pid, node.name),))
return
if node.exit_timestamp is None:
warning("ignoring incomplete node %r (didn't see exit)" % (
(node.pid,),))
return
indent = ' '*depth
wall = node.total_wall_time
user = node.total_user_time
sys = node.total_system_time
startlag = node.startlag
exitlag = node.exitlag
if opts.show_tree:
print ('%s%s -- wall: %.4fs, user: %.4fs, sys: %.4fs, '
'startlag: %.4fs, exitlag: %.4fs') % (
indent, node.name, wall, user, sys, startlag, exitlag)
key = '%s @ %d' % (node.name, depth)
aggregate_info = aggregate.get(key)
if aggregate_info is None:
aggregate[key] = aggregate_info = {
'name' : key,
'wall' : 0.0,
'user' : 0.0,
'sys' : 0.0,
'startlag' : 0.0,
'exitlag' : 0.0,
'count' : 0 }
aggregate_info['wall'] += wall
aggregate_info['user'] += user
aggregate_info['sys'] += sys
aggregate_info['startlag'] += startlag
aggregate_info['exitlag'] += exitlag
aggregate_info['count'] += 1
for c in node.children:
print_node(c, depth+1)
if not focused_roots:
parser.error("no roots found!")
aggregate = {}
for node in focused_roots:
print_node(node, depth=0)
if node is not focused_roots[-1]:
print
print
print 'Aggregate Times'
print '---------------'
items = aggregate.values()
items.sort(key = lambda i: i['wall'],
reverse = True)
name_length = max(len(item['name'])
for item in items)
for item in items:
print ('%-*s -- wall: %8.4fs, user: %8.4fs, sys: %8.4fs, '
'startlag: %8.4fs, exitlag: %.4fs, count: %d') % (
name_length, item['name'], item['wall'], item['user'], item['sys'],
item['startlag'], item['exitlag'], item['count'])
# Write out an LNT test report with the data, if requested.
if opts.lnt_report_path:
import lnt.testing
# Build the regular expression substitution arguments.
substitution_args = []
for value in opts.report_sub_args:
if '=' in value:
pattern,replacement = value.split('=',1)
else:
pattern,replacement = value,''
substitution_args.append((re.compile(pattern), replacement))
# First, organize all the nodes by deriving a test name key for them.
def group_node_and_children(node, depth = 0):
# Ignore incomplete nodes.
if node.start_timestamp is None or node.exit_timestamp is None:
return
args = node.args
if args is not None:
# If this is a clang -cc1 invocation, do some special stuff to
# normalize.
if node.name == "clang" and args and args[1] == '-cc1':
triple_index = args.index('-triple')
main_file_name_index = args.index('-main-file-name')
args = (
args[:2] +
args[triple_index:triple_index+2] + \
args[main_file_name_index:main_file_name_index+2])
# Apply substitutions to each argument.
def substitute(arg):
for pattern_re,replacement in substitution_args:
arg = pattern_re.sub(replacement, arg)
return arg
args = [substitute(arg)
for arg in args]
# Eliminate empty arguments.
args = filter(None, args)
key = '%s(depth=%d,args=%r)' % (node.name, depth, args)
items = nodes_by_key.get(key)
if items is None:
nodes_by_key[key] = items = []
items.append(node)
for child in node.children:
group_node_and_children(child, depth+1)
nodes_by_key = {}
for node in focused_roots:
group_node_and_children(node)
tag = "compile"
run_info = { "tag" : tag,
"run_order" : opts.report_run_order }
machine = lnt.testing.Machine(opts.report_machine, {})
run = lnt.testing.Run(datetime.datetime.fromtimestamp(
target_root.start_timestamp_in_seconds).\
strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.fromtimestamp(
target_root.exit_timestamp_in_seconds).\
strftime('%Y-%m-%d %H:%M:%S'),
info=run_info)
# We report in a scheme compatible with the compile time suite.
testsamples = []
for key,nodes in nodes_by_key.items():
for subkey,accessor in (('wall', 'total_wall_time'),
('user', 'total_user_time'),
('sys', 'total_system_time')):
values = [getattr(node, accessor)
for node in nodes]
name = '%s.%s.%s' % (tag, key, subkey)
testsamples.append(lnt.testing.TestSamples(
name, values))
report = lnt.testing.Report(machine, run, testsamples)
with open(opts.lnt_report_path, "w") as f:
print >>f, report.render()