summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugeni Dodonov <eugeni.dodonov@intel.com>2011-11-07 11:37:52 -0200
committerEugeni Dodonov <eugeni.dodonov@intel.com>2012-01-06 13:34:40 -0200
commitf47f8df13f9732c834b61094173b541c21cf98ad (patch)
tree01b57d8ab2103d0ad1a87f890dfb078d569aed59
parent9cdcb0fae88d472244ffd28310eefe273e14b20b (diff)
intel_gpu_analyse: analyse perf results
This allows to analyse per-second results of perf run, and output a cross-referenced statistics of the execution. Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
-rwxr-xr-xtools/intel_gpu_analyze.py117
1 files changed, 109 insertions, 8 deletions
diff --git a/tools/intel_gpu_analyze.py b/tools/intel_gpu_analyze.py
index 252e327..a9edcfe 100755
--- a/tools/intel_gpu_analyze.py
+++ b/tools/intel_gpu_analyze.py
@@ -8,9 +8,6 @@ import os
import getopt
import tempfile
-# for charts
-import pylab
-
HEADER="""
<html>
<head>
@@ -52,6 +49,30 @@ FIGURE="""
</p>
"""
+PERF_ITERATION="""
+<hr/>
+<a name="%(sec)d">
+<h3>Second %(sec)d</h3>
+</a>
+Processes in execution: <i>%(processes)s</i>
+<br/>
+"""
+
+PERF_SECOND_TITLE="""
+<a href="#%(sec)d">Second %(sec)d</a>
+<br/>
+"""
+
+PERF_PROCESS="""
+<h3>Process %(process)s</h3>
+"""
+
+PERF_TOP="""
+<pre>
+%(top)s
+</pre>
+"""
+
TAIL="""
</body>
</html>
@@ -99,6 +120,70 @@ def collect(fd):
results['blitter_ops'].append(int(data[11]))
return results
+def analyse_perf(logfile, out_dir, perf="perf.html"):
+ """Analyses perf results"""
+ perf_data = os.popen("perf script -f comm,pid,time,ip,sym -i %s 2>/dev/null" % logfile)
+ if not perf_data:
+ print "Error: unable to process perf log %s" % logfile
+ return
+ results = {}
+ time_start = -1
+ time_prev = -1
+ while 1:
+ line = perf_data.readline()
+ if not line:
+ break
+ fields = line.strip().split()
+ process = fields[0]
+ pid = int(fields[1])
+ time = float(fields[2][:-1]) # remove the trailing ':'
+ ip = fields[3]
+ if len(fields) > 4:
+ function = fields[4]
+ else:
+ function = "unknown"
+ # calculate time
+ if time_start == -1:
+ time_start = int(time) # floor down to the corresponding second
+ # are we on the next second already?
+ if time - time_start > 1.0:
+ time_start = int(time)
+ if time_start not in results:
+ results[time_start] = {}
+ # is the current process being tracked?
+ if process not in results[time_start]:
+ results[time_start][process]={}
+ # calculate times for functions
+ if function not in results[time_start][process]:
+ results[time_start][process][function] = 0
+
+ # ok, so now calculate per-function per-process stats
+ results[time_start][process][function] += (time - time_prev)
+ time_prev = time
+
+ # all done, now process the results
+ output = open("%s/%s" % (out_dir, perf), "w")
+ print >>output, HEADER % {'title': 'Perf results for %s' % logfile,
+ 'duration': len(results.keys())
+ }
+ seconds = results.keys()
+ seconds.sort()
+ for sec in seconds:
+ # print TOC
+ print >>output, PERF_SECOND_TITLE % {'sec': sec}
+ for sec in seconds:
+ print >>output, PERF_ITERATION % {'sec': sec, 'processes': ', '.join(results[sec].keys())}
+ for process in results[sec]:
+ print >>output, PERF_PROCESS % {'process': process}
+ # let's sort functions
+ functions_by_time = sorted(results[sec][process], key=lambda key: results[sec][process][key], reverse=True)
+ top = ""
+ for function in functions_by_time:
+ top += "%.6f\t\t%s\n" % (results[sec][process][function], function)
+ print >>output, PERF_TOP % { 'top': top }
+ print >>output, TAIL
+ output.close()
+
def analyse(results, title, out_dir, summary="index.html"):
"""Analyses intel_gpu_top results"""
# calculate min/max/avg values
@@ -147,6 +232,11 @@ def analyse(results, title, out_dir, summary="index.html"):
}
# graphics
+ try:
+ import pylab
+ except:
+ print "Error: unable to import pylab: %s" % sys.exc_value
+ return
fig = pylab.figure()
ax = pylab.subplot(111)
pylab.title("Summary of CPU/GPU/Power usage")
@@ -304,6 +394,7 @@ def analyse(results, title, out_dir, summary="index.html"):
pass
print >>output, TAIL
+ output.close()
def usage(cmd):
"""Prints usage message"""
@@ -317,8 +408,11 @@ The following arguments are accepted:
-c, --command command to profile
-t, --title description of the command analysed
-o, --output output directory for the results
+ -p, --perf kernel perf log file to analyse.
+
+You need to specify either a log file to analyse, or a command to profile,
+or a perf log file to process.
-You need to specify either a log file to analyse, or a command to profile.
When you specify both -l and -c, the last one takes predence.
If you do not give a log file to analyse, or a command to profile, this
@@ -329,11 +423,12 @@ you will feel bad about it.
if __name__ == "__main__":
# parse command line
try:
- opt, args = getopt.getopt(sys.argv[1:], 'hl:c:t:o:', ['help', 'logfile=', 'command=', 'title=', 'output='])
+ opt, args = getopt.getopt(sys.argv[1:], 'hl:c:t:o:p:', ['help', 'logfile=', 'command=', 'title=', 'output=', 'perf='])
except getopt.error:
usage(sys.argv[0])
sys.exit(1)
logfile = None
+ perf_logfile = None
title = None
output = os.curdir
for o in opt:
@@ -342,6 +437,9 @@ if __name__ == "__main__":
usage(sys.argv[0])
sys.exit(0)
# list
+ elif o[0] == '-p' or o[0] == '--perf':
+ perf_logfile = o[1]
+ print "Analysing perf log file: %s" % perf_logfile
elif o[0] == '-l' or o[0] == '--logfile':
logfile = open(o[1], "r")
title = "Log file '%s'" % o[1]
@@ -353,7 +451,7 @@ if __name__ == "__main__":
title = o[1]
elif o[0] == '-o' or o[0] == '--output':
output = o[1]
- if not logfile:
+ if not logfile and not perf_logfile:
usage(sys.argv[0])
print "Error: no log file and no command to profile, don't know what to do"
sys.exit(1)
@@ -361,5 +459,8 @@ if __name__ == "__main__":
os.makedirs(output)
except:
pass
- results = collect(logfile)
- analyse(results, title, output)
+ if logfile:
+ results = collect(logfile)
+ analyse(results, title, output)
+ if perf_logfile:
+ analyse_perf(perf_logfile, output)