OSDN Git Service

a5cdbac850de5bf8cf68525b62caf8f6c02d43bb
[android-x86/system-extras.git] / perfprofd / scripts / perf_proto_stack.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2017 The Android Open Source Project
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Super simplistic printer of a perfprofd output proto. Illustrates
18 # how to parse and traverse a perfprofd output proto in Python.
19
20 # Generate with:
21 #  aprotoc -I=system/extras/perfprofd --python_out=system/extras/perfprofd/scripts \
22 #      system/extras/perfprofd/perf_profile.proto
23 import perf_profile_pb2
24
25 # Make sure that symbol is on the PYTHONPATH, e.g., run as
26 # PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/development/scripts python ...
27 import symbol
28
29 # This is wrong. But then the symbol module is a bad quagmire.
30 symbol.SetAbi(["ABI: 'arm64'"])
31 print "Reading symbols from", symbol.SYMBOLS_DIR
32
33 # TODO: accept argument for parsing.
34 file = open('perf.data.encoded.0', 'rb')
35 data = file.read()
36
37 profile = perf_profile_pb2.AndroidPerfProfile()
38 profile.ParseFromString(data)
39
40 print "Total samples: ", profile.total_samples
41
42 module_list = profile.load_modules
43
44 counters = {}
45
46 print 'Samples:'
47 for program in profile.programs:
48     print program.name
49     for module in program.modules:
50         if module.HasField('load_module_id'):
51             module_descr = module_list[module.load_module_id]
52             print ' ', module_descr.name
53             has_build_id = module_descr.HasField('build_id')
54             if has_build_id:
55                 print '   ', module_descr.build_id
56             for addr in module.address_samples:
57                 # TODO: Stacks vs single samples.
58                 addr_rel = addr.address[0]
59                 print '     ', addr.count, addr_rel
60                 if module_descr.name != '[kernel.kallsyms]':
61                     addr_rel_hex = "%x" % addr_rel
62                     if has_build_id:
63                         info = symbol.SymbolInformation(module_descr.name, addr_rel_hex)
64                         # As-is, only info[0] (inner-most inlined function) is recognized.
65                         (source_symbol, source_location, object_symbol_with_offset) = info[0]
66                         if source_symbol is not None:
67                             print source_symbol, source_location, object_symbol_with_offset
68                     elif module_descr.symbol and (addr_rel & 0x8000000000000000 != 0):
69                         index = 0xffffffffffffffff - addr_rel
70                         source_symbol = module_descr.symbol[index]
71                     counters_key = None
72                     if source_symbol is not None:
73                         counters_key = (module_descr.name, source_symbol)
74                     else:
75                         counters_key = (module_descr.name, addr_rel_hex)
76                     if counters_key in counters:
77                         counters[counters_key] = counters[counters_key] + addr.count
78                     else:
79                         counters[counters_key] = addr.count
80         else:
81             print '  Missing module'
82
83 print 'Modules:'
84 for module in module_list:
85     print ' ', module.name
86     if module.HasField('build_id'):
87         print '   ', module.build_id
88     for symbol in module.symbol:
89         print '      ', symbol
90
91 # Create a sorted list of top samples.
92 counter_list = []
93 for key, value in counters.iteritems():
94     temp = (key,value)
95     counter_list.append(temp)
96 counter_list.sort(key=lambda counter: counter[1], reverse=True)
97
98 # Print top-100 samples.
99 for i in range(0, 100):
100     print i+1, counter_list[i]