| """ |
| perf is a tool included in the linux kernel tree that |
| supports functionality similar to oprofile and more. |
| |
| @see: http://lwn.net/Articles/310260/ |
| """ |
| |
| import time, os, stat, subprocess, signal |
| import logging |
| from autotest_lib.client.bin import profiler, os_dep, utils |
| |
| |
| class perf(profiler.profiler): |
| version = 1 |
| |
| def initialize(self, events=["cycles","instructions"], trace=False): |
| if type(events) == str: |
| self.events = [events] |
| else: |
| self.events = events |
| self.trace = trace |
| self.perf_bin = os_dep.command('perf') |
| perf_help = utils.run('%s report help' % self.perf_bin, |
| ignore_status=True).stderr |
| self.sort_keys = None |
| for line in perf_help.split('\n'): |
| a = "sort by key(s):" |
| if a in line: |
| line = line.replace(a, "") |
| self.sort_keys = [k.rstrip(",") for k in line.split() if |
| k.rstrip(",") != 'dso'] |
| if not self.sort_keys: |
| self.sort_keys = ['comm', 'cpu'] |
| |
| |
| def start(self, test): |
| self.logfile = os.path.join(test.profdir, "perf") |
| cmd = ("exec %s record -a -o %s" % |
| (self.perf_bin, self.logfile)) |
| if "parent" in self.sort_keys: |
| cmd += " -g" |
| if self.trace: |
| cmd += " -R" |
| for event in self.events: |
| cmd += " -e %s" % event |
| self._process = subprocess.Popen(cmd, shell=True, |
| stderr=subprocess.STDOUT) |
| |
| |
| def stop(self, test): |
| os.kill(self._process.pid, signal.SIGINT) |
| self._process.wait() |
| |
| |
| def report(self, test): |
| for key in self.sort_keys: |
| reportfile = os.path.join(test.profdir, '%s.comm' % key) |
| cmd = ("%s report -i %s --sort %s,dso" % (self.perf_bin, |
| self.logfile, |
| key)) |
| outfile = open(reportfile, 'w') |
| p = subprocess.Popen(cmd, shell=True, stdout=outfile, |
| stderr=subprocess.STDOUT) |
| p.wait() |
| |
| if self.trace: |
| tracefile = os.path.join(test.profdir, 'trace') |
| cmd = ("%s script -i %s" % (self.perf_bin, self.logfile,)) |
| |
| outfile = open(tracefile, 'w') |
| p = subprocess.Popen(cmd, shell=True, stdout=outfile, |
| stderr=subprocess.STDOUT) |
| p.wait() |
| |
| # The raw detailed perf output is HUGE. We cannot store it by default. |
| perf_log_size = os.stat(self.logfile)[stat.ST_SIZE] |
| logging.info('Removing %s after generating reports (saving %s bytes).', |
| self.logfile, perf_log_size) |
| os.unlink(self.logfile) |