1""" 2perf is a tool included in the linux kernel tree that 3supports functionality similar to oprofile and more. 4 5@see: http://lwn.net/Articles/310260/ 6""" 7 8import time, os, stat, subprocess, signal 9import logging 10from autotest_lib.client.bin import profiler, os_dep, utils 11 12 13class perf(profiler.profiler): 14 version = 1 15 16 def initialize(self, events=["cycles","instructions"], trace=False): 17 if type(events) == str: 18 self.events = [events] 19 else: 20 self.events = events 21 self.trace = trace 22 self.perf_bin = os_dep.command('perf') 23 perf_help = utils.run('%s report help' % self.perf_bin, 24 ignore_status=True).stderr 25 self.sort_keys = None 26 for line in perf_help.split('\n'): 27 a = "sort by key(s):" 28 if a in line: 29 line = line.replace(a, "") 30 self.sort_keys = [k.rstrip(",") for k in line.split() if 31 k.rstrip(",") != 'dso'] 32 if not self.sort_keys: 33 self.sort_keys = ['comm', 'cpu'] 34 35 36 def start(self, test): 37 self.logfile = os.path.join(test.profdir, "perf") 38 cmd = ("exec %s record -a -o %s" % 39 (self.perf_bin, self.logfile)) 40 if "parent" in self.sort_keys: 41 cmd += " -g" 42 if self.trace: 43 cmd += " -R" 44 for event in self.events: 45 cmd += " -e %s" % event 46 self._process = subprocess.Popen(cmd, shell=True, 47 stderr=subprocess.STDOUT) 48 49 50 def stop(self, test): 51 os.kill(self._process.pid, signal.SIGINT) 52 self._process.wait() 53 54 55 def report(self, test): 56 for key in self.sort_keys: 57 reportfile = os.path.join(test.profdir, '%s.comm' % key) 58 cmd = ("%s report -i %s --sort %s,dso" % (self.perf_bin, 59 self.logfile, 60 key)) 61 outfile = open(reportfile, 'w') 62 p = subprocess.Popen(cmd, shell=True, stdout=outfile, 63 stderr=subprocess.STDOUT) 64 p.wait() 65 66 if self.trace: 67 tracefile = os.path.join(test.profdir, 'trace') 68 cmd = ("%s script -i %s" % (self.perf_bin, self.logfile,)) 69 70 outfile = open(tracefile, 'w') 71 p = subprocess.Popen(cmd, shell=True, stdout=outfile, 72 stderr=subprocess.STDOUT) 73 p.wait() 74 75 # The raw detailed perf output is HUGE. We cannot store it by default. 76 perf_log_size = os.stat(self.logfile)[stat.ST_SIZE] 77 logging.info('Removing %s after generating reports (saving %s bytes).', 78 self.logfile, perf_log_size) 79 os.unlink(self.logfile) 80