Warning, file /sdk/heaptrack/tests/manual/perf-heaptrack.py was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 # 0002 # A script to convert perf data files into the heaptrack format. 0003 # 0004 # perf script -s perf-heaptrack.py -i perf.data | gzip > perf.heaptrack.gz 0005 # heaptrack_gui perf.heaptrack.gz 0006 # 0007 # This is mostly a proof-of-concept to show how this could be used 0008 # in the future to visualize perf results. 0009 # 0010 # SPDX-FileCopyrightText: 2016-2017 Milian Wolff <mail@milianw.de> 0011 # 0012 # SPDX-License-Identifier: LGPL-2.1-or-later 0013 # 0014 0015 import os 0016 import sys 0017 import json 0018 import subprocess 0019 from collections import defaultdict 0020 0021 sys.path.append(os.environ["PERF_EXEC_PATH"] + "/scripts/python/Perf-Trace-Util/lib/Perf/Trace") 0022 0023 from perf_trace_context import * 0024 0025 try: 0026 from subprocess import DEVNULL # py3k 0027 except ImportError: 0028 import os 0029 DEVNULL = open(os.devnull, 'wb') 0030 0031 class FileInfo: 0032 def __init__(self, file, line): 0033 self.file = file 0034 self.line = line 0035 0036 class InternMap: 0037 def __init__(self): 0038 self.map = dict() 0039 self.map[""] = 0; 0040 0041 def add(self, string): 0042 nextIndex = len(self.map) 0043 index = self.map.get(string, nextIndex) 0044 if index == nextIndex: 0045 print("s %s" % string) 0046 self.map[string] = nextIndex 0047 return nextIndex 0048 return index 0049 0050 strings = InternMap() 0051 0052 def addr2line(dsoName, address): 0053 try: 0054 output = subprocess.check_output(["addr2line", "-e", dsoName, hex(address)], stderr=DEVNULL).split(':') 0055 file = output[0] 0056 if not file or file == "??": 0057 raise "error" 0058 line = int(output[1]) 0059 return FileInfo(file, line) 0060 except: 0061 return FileInfo("???", 0) 0062 0063 nextIpIndex = 1 0064 class InstructionPointerMap: 0065 def __init__(self): 0066 self.map = dict() 0067 0068 def add(self, ip, dsoName, name, sym): 0069 ipEntry = self.map.get(ip, None) 0070 if ipEntry == None: 0071 global nextIpIndex 0072 ipEntry = nextIpIndex 0073 nextIpIndex += 1 0074 fileInfo = addr2line(dsoName, ip) 0075 print("i %x %x %x %x %d" % (ip, strings.add(dsoName), strings.add(name), strings.add(fileInfo.file), fileInfo.line)) 0076 self.map[ip] = ipEntry 0077 return ipEntry 0078 ipMap = InstructionPointerMap() 0079 0080 nextTraceIndex = 1 0081 class TraceEntry: 0082 def __init__(self, traceIndex): 0083 self.index = traceIndex 0084 self.children = dict() 0085 0086 def add(self, ipIndex): 0087 child = self.children.get(ipIndex, None) 0088 if child == None: 0089 global nextTraceIndex 0090 child = TraceEntry(nextTraceIndex) 0091 nextTraceIndex += 1 0092 print("t %x %x" % (ipIndex, self.index)) 0093 self.children[ipIndex] = child 0094 return child 0095 0096 traceRoot = TraceEntry(0) 0097 0098 nextSampleIndex = 0 0099 class SampleMap: 0100 def __init__(self): 0101 self.map = dict() 0102 0103 def add(self, traceIndex): 0104 sampleIndex = self.map.get(traceIndex, None) 0105 if sampleIndex == None: 0106 global nextSampleIndex 0107 sampleIndex = nextSampleIndex 0108 nextSampleIndex += 1 0109 print("a 1 %x" % (traceIndex)) 0110 self.map[traceIndex] = sampleIndex 0111 return sampleIndex 0112 samples = SampleMap() 0113 0114 # write the callgrind file format to stdout 0115 def trace_begin(): 0116 print("v 10000") 0117 print("# perf.data converted using perf-heaptrack.py") 0118 0119 # this function gets called for every sample 0120 # the event dict contains information about the symbol, time, callchain, ... 0121 # print it out to peek inside! 0122 startTime = 0 0123 lastTime = 0 0124 finalTime = 0 0125 0126 def trace_end(): 0127 print("c %x" % (finalTime + 1)) 0128 0129 def process_event(event): 0130 global startTime, lastTime, finalTime 0131 if startTime == 0: 0132 startTime = event["sample"]["time"] 0133 elapsed = (event["sample"]["time"] - startTime) / 10000000 0134 if (lastTime + 1) <= elapsed: 0135 print("c %x" % elapsed) 0136 lastTime = elapsed 0137 finalTime = elapsed 0138 0139 global ipMap, traceRoot, samples 0140 trace = traceRoot 0141 if not event["callchain"]: 0142 dsoName = event.get("dso", "???") 0143 name = event.get("symbol", "???") 0144 ipIndex = ipMap.add(event["sample"]["ip"], dsoName, name, None) 0145 traceIndex = trace.add(ipIndex).index 0146 else: 0147 # add a function for every frame in the callchain 0148 for item in reversed(event["callchain"]): 0149 dsoName = item.get("dso", "???") 0150 name = "???" 0151 if "sym" in item: 0152 name = item["sym"]["name"] 0153 ipIndex = ipMap.add(item["ip"], dsoName, name, item.get("sym", None)) 0154 trace = trace.add(ipIndex) 0155 traceIndex = trace.index 0156 sampleIndex = samples.add(traceIndex) 0157 print("+ %x" % sampleIndex)