Skip to content
This repository was archived by the owner on May 29, 2025. It is now read-only.

Commit be07ba7

Browse files
surkiSuresh Kumar
authored andcommitted
Make flamegraph generation python script more flexible
Add commandline options to control how the flamegraphs are generated. Useful in automated environment and/or manual invocation of the script to generate flamegraphs
1 parent d7100e3 commit be07ba7

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ Kristof Mattei
1212
Alexander Riccio
1313
Bradley Grainger
1414
Michael Winterberg
15+
Suresh Kumar Ponnusamy

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Kristof Mattei
1414
Alexander Riccio
1515
Bradley Grainger
1616
Michael Winterberg
17+
Suresh Kumar Ponnusamy

bin/xperf_to_collapsedstacks.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,28 @@
3434
import os
3535
import time
3636
import subprocess
37+
import argparse
38+
39+
parser = argparse.ArgumentParser(description='Process xperf ETL file and generate flamegraph(s).')
40+
parser.add_argument('etlFilename', metavar='FILE', type=str,
41+
help='Path to ETL file')
42+
parser.add_argument('-p', '--processlist', help='List of process names to generate flamegraph for. Comma separated.', type=str)
43+
parser.add_argument('-b', '--begin', help='Time range. Begin from the specified value. In seconds.', type=float)
44+
parser.add_argument('-e', '--end', help='Time range. End at the specified value. In seconds.', type=float)
45+
parser.add_argument('-o', '--output', help='Path to directory where output will written into. Default is system TEMP directory', type=str)
46+
parser.set_defaults(output=os.environ["temp"])
47+
parser.add_argument('-n', '--numshow', help='Number of top processes to generate flame graph for. Default is 1', type=int)
48+
parser.set_defaults(numshow=1)
49+
parser.add_argument('-d', '--dontopen', help='Do not open the generated SVG file automatically. Default is open', action='store_true')
50+
parser.set_defaults(dontopen=False)
51+
args = parser.parse_args()
52+
53+
processList = []
54+
if args.processlist:
55+
processList = [item.lower() for item in args.processlist.split(',')]
3756

3857
# How many threads to create collapsed stacks for.
39-
numToShow = 1
58+
numToShow = args.numshow
4059

4160
scriptPath = os.path.abspath(sys.argv[0])
4261
scriptDir = os.path.split(scriptPath)[0]
@@ -63,18 +82,10 @@
6382
print "Couldn't find \"%s\". Make sure WPT 10 is installed." % wpaExporterPath
6483
sys.exit(0)
6584

66-
if len(sys.argv) < 2:
67-
print "Usage: %s trace.etl begin end" % sys.argv[0]
68-
print "Begin and end specify the time range to be processed, in seconds."
69-
sys.exit(0)
70-
71-
etlFilename = sys.argv[1]
72-
if len(sys.argv) >= 4:
73-
begin = float(sys.argv[2])
74-
end = float(sys.argv[3])
75-
wpaCommand = r'"%s" "%s" -range %ss %ss -profile "%s" -symbols' % (wpaExporterPath, etlFilename, begin, end, profilePath)
85+
if args.begin and args.end:
86+
wpaCommand = r'"%s" "%s" -range %ss %ss -profile "%s" -symbols' % (wpaExporterPath, args.etlFilename, args.begin, args.end, profilePath)
7687
else:
77-
wpaCommand = r'"%s" "%s" -profile "%s" -symbols' % (wpaExporterPath, etlFilename, profilePath)
88+
wpaCommand = r'"%s" "%s" -profile "%s" -symbols' % (wpaExporterPath, args.etlFilename, profilePath)
7889

7990
print "> %s" % wpaCommand
8091
start = time.clock()
@@ -97,6 +108,8 @@
97108
line = line.strip()
98109
firstCommaPos = line.find(",")
99110
process = line[:firstCommaPos]
111+
if processList and process.split(' ')[0].lower() not in processList:
112+
continue
100113
secondCommaPos = line.find(",", firstCommaPos + 1)
101114
threadID = line[firstCommaPos + 1 : secondCommaPos]
102115
stackSummary = line[secondCommaPos + 1:]
@@ -145,11 +158,13 @@
145158

146159
print "Found %d samples from %d threads." % (totalSamples, len(samples))
147160

148-
tempDir = os.environ["temp"]
161+
if len(processList)>0:
162+
numToShow = len(sortedThreads)
163+
149164
count = 0
150165
for numSamples, processAndThread in sortedThreads[:numToShow]:
151166
threadSamples = samples[processAndThread]
152-
outputName = os.path.join(tempDir, "collapsed_stacks_%d.txt" % count)
167+
outputName = os.path.join(args.output, "collapsed_stacks_%d.txt" % count)
153168
count += 1
154169
print "Writing %d samples to temporary file %s" % (numSamples, outputName)
155170
sortedStacks = []
@@ -166,14 +181,15 @@
166181
# perl script is run.
167182
out.close()
168183

169-
destPath = os.path.join(tempDir, "%s.svg" % processAndThread)
184+
destPath = os.path.join(args.output, "%s.svg" % processAndThread)
170185
title = "CPU Usage flame graph of %s" % processAndThread
171186
perlCommand = 'perl "%s" --title="%s" "%s"' % (flameGraphPath, title, outputName)
172187
print "> %s" % perlCommand
173188
svgOutput = subprocess.check_output(perlCommand)
174189
if len(svgOutput) > 100:
175190
open(destPath, "wt").write(svgOutput)
176-
os.popen(destPath)
191+
if not args.dontopen:
192+
os.popen(destPath)
177193
print 'Results are in "%s" - they should be auto-opened in the default SVG viewer.' % destPath
178194
else:
179195
print "Result size is %d bytes - is perl in your path?" % len(svgOutput)

0 commit comments

Comments
 (0)