-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathperf2gv
More file actions
executable file
·113 lines (102 loc) · 3.37 KB
/
perf2gv
File metadata and controls
executable file
·113 lines (102 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/python3
# Copyright 2013 William Cohen <wcohen@redhat.com>
# Copyright 2013 Red Hat, Inc.
# Copyright 2014 Red Hat, Inc.
# Copyright 2018 Red Hat, Inc.
#
# This is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
# This simple script convert the perf report output for something that
# has callgraph information into a graphviz output
import fileinput
import re
import getopt
import os
import sys
def usage(name):
print(('''usage: %s [<options>] < perf_output > call_graph_file
options:
\t[-h|--help]''' \
% (name)))
def header():
result = 'digraph Callgraph {\n'
result += ' node [shape=ellipse];\n'
return result
def footer():
result = '}\n'
return result
# func@plt should just be treated the same as a direct call the func
def extract_func(func):
return re.sub(r'@plt', "", func)
def body(threshold, const):
#munge the output to give a call graph information
result = ''
counts = { }
subgraphs = { }
for line in fileinput.input():
#skip comments and blank lines
if line.startswith("#"):
continue
element = line.split()
if len(element) < 8:
continue
weight = float(element[0].replace("%","")) / 100.00 * const
if weight > threshold:
caller_bin = element[2]
caller = extract_func(element[4])
callee_bin = element[5]
callee = extract_func(element[7])
counts[(' "%s" -> "%s" ' % (caller, callee))] = weight
# add function to subgraph
if caller_bin in subgraphs :
subgraphs[caller_bin].add(caller)
else:
subgraphs[caller_bin] = set([ caller ])
if callee_bin in subgraphs :
subgraphs[callee_bin].add(callee)
else:
subgraphs[callee_bin] = set([ callee ])
# print out subgraphs
i = 0
for graph in subgraphs:
result += (' subgraph cluster%d {\n' % i)
for node in subgraphs[graph]:
result += (' "%s" ;\n' % node)
result += (' label = "%s";\n' % graph)
result += (' }\n\n')
i = i + 1
# Print the accumulated edges
for edge_name in counts:
result += (' %s ' % edge_name)
result += ('[ label = %.6f ];\n' % counts[edge_name])
return result
argv0 = os.path.basename(sys.argv[0])
# parse options
try:
(opt, args) = getopt.getopt(sys.argv[1:],
'h',
['help',
])
except getopt.GetoptError as e:
print(("%s: %s" % (argv0, e)))
usage(argv0)
sys.exit(1)
# process command line options
for o in opt:
if o[0] in ('-h', '--help'):
usage(argv0)
sys.exit(0)
print(header())
print(body(0.000, 1.0))
print(footer())