3 # Copyright (C) 2017 The Android Open Source Project
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Super simplistic printer of a perfprofd output proto. Illustrates
18 # how to parse and traverse a perfprofd output proto in Python.
21 # aprotoc -I=system/extras/perfprofd --python_out=system/extras/perfprofd/scripts \
22 # system/extras/perfprofd/perf_profile.proto
23 import perf_profile_pb2
25 # Make sure that symbol is on the PYTHONPATH, e.g., run as
26 # PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/development/scripts python ...
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
33 # TODO: accept argument for parsing.
34 file = open('perf.data.encoded.0', 'rb')
37 profile = perf_profile_pb2.AndroidPerfProfile()
38 profile.ParseFromString(data)
40 print "Total samples: ", profile.total_samples
42 module_list = profile.load_modules
47 for program in profile.programs:
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')
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
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]
72 if source_symbol is not None:
73 counters_key = (module_descr.name, source_symbol)
75 counters_key = (module_descr.name, addr_rel_hex)
76 if counters_key in counters:
77 counters[counters_key] = counters[counters_key] + addr.count
79 counters[counters_key] = addr.count
81 print ' Missing module'
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:
91 # Create a sorted list of top samples.
93 for key, value in counters.iteritems():
95 counter_list.append(temp)
96 counter_list.sort(key=lambda counter: counter[1], reverse=True)
98 # Print top-100 samples.
99 for i in range(0, 100):
100 print i+1, counter_list[i]