From: Emil Velikov Date: Wed, 22 Feb 2017 15:14:15 +0000 (+0000) Subject: bin/perf-annotate-jit: add .py suffix X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d73603fcdd63376080e90d03d96de402386c34f8;p=mesa.git bin/perf-annotate-jit: add .py suffix To provide direct feedback about the file in question. Signed-off-by: Emil Velikov Reviewed-by: Jose Fonseca Reviewed-by: Eric Engestrom --- diff --git a/bin/perf-annotate-jit b/bin/perf-annotate-jit deleted file mode 100755 index 746434008fd..00000000000 --- a/bin/perf-annotate-jit +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 VMware Inc -# Copyright 2008-2009 Jose Fonseca -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -"""Perf annotate for JIT code. - -Linux `perf annotate` does not work with JIT code. This script takes the data -produced by `perf script` command, plus the diassemblies outputed by gallivm -into /tmp/perf-XXXXX.map.asm and produces output similar to `perf annotate`. - -See docs/llvmpipe.html for usage instructions. - -The `perf script` output parser was derived from the gprof2dot.py script. -""" - - -import sys -import os.path -import re -import optparse -import subprocess - - -class Parser: - """Parser interface.""" - - def __init__(self): - pass - - def parse(self): - raise NotImplementedError - - -class LineParser(Parser): - """Base class for parsers that read line-based formats.""" - - def __init__(self, file): - Parser.__init__(self) - self._file = file - self.__line = None - self.__eof = False - self.line_no = 0 - - def readline(self): - line = self._file.readline() - if not line: - self.__line = '' - self.__eof = True - else: - self.line_no += 1 - self.__line = line.rstrip('\r\n') - - def lookahead(self): - assert self.__line is not None - return self.__line - - def consume(self): - assert self.__line is not None - line = self.__line - self.readline() - return line - - def eof(self): - assert self.__line is not None - return self.__eof - - -mapFile = None - -def lookupMap(filename, matchSymbol): - global mapFile - mapFile = filename - stream = open(filename, 'rt') - for line in stream: - start, length, symbol = line.split() - - start = int(start, 16) - length = int(length,16) - - if symbol == matchSymbol: - return start - - return None - -def lookupAsm(filename, desiredFunction): - stream = open(filename + '.asm', 'rt') - while stream.readline() != desiredFunction + ':\n': - pass - - asm = [] - line = stream.readline().strip() - while line: - addr, instr = line.split(':', 1) - addr = int(addr) - asm.append((addr, instr)) - line = stream.readline().strip() - - return asm - - - -samples = {} - - -class PerfParser(LineParser): - """Parser for linux perf callgraph output. - - It expects output generated with - - perf record -g - perf script - """ - - def __init__(self, infile, symbol): - LineParser.__init__(self, infile) - self.symbol = symbol - - def readline(self): - # Override LineParser.readline to ignore comment lines - while True: - LineParser.readline(self) - if self.eof() or not self.lookahead().startswith('#'): - break - - def parse(self): - # read lookahead - self.readline() - - while not self.eof(): - self.parse_event() - - asm = lookupAsm(mapFile, self.symbol) - - addresses = samples.keys() - addresses.sort() - total_samples = 0 - - sys.stdout.write('%s:\n' % self.symbol) - for address, instr in asm: - try: - sample = samples.pop(address) - except KeyError: - sys.stdout.write(6*' ') - else: - sys.stdout.write('%6u' % (sample)) - total_samples += sample - sys.stdout.write('%6u: %s\n' % (address, instr)) - print 'total:', total_samples - assert len(samples) == 0 - - sys.exit(0) - - def parse_event(self): - if self.eof(): - return - - line = self.consume() - assert line - - callchain = self.parse_callchain() - if not callchain: - return - - def parse_callchain(self): - callchain = [] - while self.lookahead(): - function = self.parse_call(len(callchain) == 0) - if function is None: - break - callchain.append(function) - if self.lookahead() == '': - self.consume() - return callchain - - call_re = re.compile(r'^\s+(?P
[0-9a-fA-F]+)\s+(?P.*)\s+\((?P[^)]*)\)$') - - def parse_call(self, first): - line = self.consume() - mo = self.call_re.match(line) - assert mo - if not mo: - return None - - if not first: - return None - - function_name = mo.group('symbol') - if not function_name: - function_name = mo.group('address') - - module = mo.group('module') - - function_id = function_name + ':' + module - - address = mo.group('address') - address = int(address, 16) - - if function_name != self.symbol: - return None - - start_address = lookupMap(module, function_name) - address -= start_address - - #print function_name, module, address - - samples[address] = samples.get(address, 0) + 1 - - return True - - -def main(): - """Main program.""" - - optparser = optparse.OptionParser( - usage="\n\t%prog [options] symbol_name") - (options, args) = optparser.parse_args(sys.argv[1:]) - if len(args) != 1: - optparser.error('wrong number of arguments') - - symbol = args[0] - - p = subprocess.Popen(['perf', 'script'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - parser = PerfParser(p.stdout, symbol) - parser.parse() - - -if __name__ == '__main__': - main() - - -# vim: set sw=4 et: diff --git a/bin/perf-annotate-jit.py b/bin/perf-annotate-jit.py new file mode 100755 index 00000000000..746434008fd --- /dev/null +++ b/bin/perf-annotate-jit.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright 2012 VMware Inc +# Copyright 2008-2009 Jose Fonseca +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +"""Perf annotate for JIT code. + +Linux `perf annotate` does not work with JIT code. This script takes the data +produced by `perf script` command, plus the diassemblies outputed by gallivm +into /tmp/perf-XXXXX.map.asm and produces output similar to `perf annotate`. + +See docs/llvmpipe.html for usage instructions. + +The `perf script` output parser was derived from the gprof2dot.py script. +""" + + +import sys +import os.path +import re +import optparse +import subprocess + + +class Parser: + """Parser interface.""" + + def __init__(self): + pass + + def parse(self): + raise NotImplementedError + + +class LineParser(Parser): + """Base class for parsers that read line-based formats.""" + + def __init__(self, file): + Parser.__init__(self) + self._file = file + self.__line = None + self.__eof = False + self.line_no = 0 + + def readline(self): + line = self._file.readline() + if not line: + self.__line = '' + self.__eof = True + else: + self.line_no += 1 + self.__line = line.rstrip('\r\n') + + def lookahead(self): + assert self.__line is not None + return self.__line + + def consume(self): + assert self.__line is not None + line = self.__line + self.readline() + return line + + def eof(self): + assert self.__line is not None + return self.__eof + + +mapFile = None + +def lookupMap(filename, matchSymbol): + global mapFile + mapFile = filename + stream = open(filename, 'rt') + for line in stream: + start, length, symbol = line.split() + + start = int(start, 16) + length = int(length,16) + + if symbol == matchSymbol: + return start + + return None + +def lookupAsm(filename, desiredFunction): + stream = open(filename + '.asm', 'rt') + while stream.readline() != desiredFunction + ':\n': + pass + + asm = [] + line = stream.readline().strip() + while line: + addr, instr = line.split(':', 1) + addr = int(addr) + asm.append((addr, instr)) + line = stream.readline().strip() + + return asm + + + +samples = {} + + +class PerfParser(LineParser): + """Parser for linux perf callgraph output. + + It expects output generated with + + perf record -g + perf script + """ + + def __init__(self, infile, symbol): + LineParser.__init__(self, infile) + self.symbol = symbol + + def readline(self): + # Override LineParser.readline to ignore comment lines + while True: + LineParser.readline(self) + if self.eof() or not self.lookahead().startswith('#'): + break + + def parse(self): + # read lookahead + self.readline() + + while not self.eof(): + self.parse_event() + + asm = lookupAsm(mapFile, self.symbol) + + addresses = samples.keys() + addresses.sort() + total_samples = 0 + + sys.stdout.write('%s:\n' % self.symbol) + for address, instr in asm: + try: + sample = samples.pop(address) + except KeyError: + sys.stdout.write(6*' ') + else: + sys.stdout.write('%6u' % (sample)) + total_samples += sample + sys.stdout.write('%6u: %s\n' % (address, instr)) + print 'total:', total_samples + assert len(samples) == 0 + + sys.exit(0) + + def parse_event(self): + if self.eof(): + return + + line = self.consume() + assert line + + callchain = self.parse_callchain() + if not callchain: + return + + def parse_callchain(self): + callchain = [] + while self.lookahead(): + function = self.parse_call(len(callchain) == 0) + if function is None: + break + callchain.append(function) + if self.lookahead() == '': + self.consume() + return callchain + + call_re = re.compile(r'^\s+(?P
[0-9a-fA-F]+)\s+(?P.*)\s+\((?P[^)]*)\)$') + + def parse_call(self, first): + line = self.consume() + mo = self.call_re.match(line) + assert mo + if not mo: + return None + + if not first: + return None + + function_name = mo.group('symbol') + if not function_name: + function_name = mo.group('address') + + module = mo.group('module') + + function_id = function_name + ':' + module + + address = mo.group('address') + address = int(address, 16) + + if function_name != self.symbol: + return None + + start_address = lookupMap(module, function_name) + address -= start_address + + #print function_name, module, address + + samples[address] = samples.get(address, 0) + 1 + + return True + + +def main(): + """Main program.""" + + optparser = optparse.OptionParser( + usage="\n\t%prog [options] symbol_name") + (options, args) = optparser.parse_args(sys.argv[1:]) + if len(args) != 1: + optparser.error('wrong number of arguments') + + symbol = args[0] + + p = subprocess.Popen(['perf', 'script'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + parser = PerfParser(p.stdout, symbol) + parser.parse() + + +if __name__ == '__main__': + main() + + +# vim: set sw=4 et: diff --git a/docs/llvmpipe.html b/docs/llvmpipe.html index 42272151c3b..2efbbd4ca61 100644 --- a/docs/llvmpipe.html +++ b/docs/llvmpipe.html @@ -206,7 +206,7 @@ On Linux, it is possible to have symbol resolution of JIT code with