1cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr"""
2cefc0f9eb9996bc9da9098a886e659c0578dbe00lmrperf is a tool included in the linux kernel tree that
3cefc0f9eb9996bc9da9098a886e659c0578dbe00lmrsupports functionality similar to oprofile and more.
4cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
5cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr@see: http://lwn.net/Articles/310260/
6cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr"""
7cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
86f27d4f22a1ba5063968b8c322fa0845f3279adeEric Liimport time, os, stat, subprocess, signal
96f27d4f22a1ba5063968b8c322fa0845f3279adeEric Liimport logging
10cefc0f9eb9996bc9da9098a886e659c0578dbe00lmrfrom autotest_lib.client.bin import profiler, os_dep, utils
11cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
12cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
13cefc0f9eb9996bc9da9098a886e659c0578dbe00lmrclass perf(profiler.profiler):
14cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr    version = 1
15cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
1674a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis    def initialize(self, events=["cycles","instructions"], trace=False):
17d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li        if type(events) == str:
18d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li            self.events = [events]
19d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li        else:
20d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li            self.events = events
2122434d4311581dde7a3bb51eef03a27d757aa263Eric Li        self.trace = trace
22cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        self.perf_bin = os_dep.command('perf')
23cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        perf_help = utils.run('%s report help' % self.perf_bin,
24cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr                              ignore_status=True).stderr
25cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        self.sort_keys = None
26cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        for line in perf_help.split('\n'):
27cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr            a = "sort by key(s):"
28cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr            if a in line:
2922434d4311581dde7a3bb51eef03a27d757aa263Eric Li                line = line.replace(a, "")
30cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr                self.sort_keys = [k.rstrip(",") for k in line.split() if
31cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr                                  k.rstrip(",") != 'dso']
32cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        if not self.sort_keys:
33cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr            self.sort_keys = ['comm', 'cpu']
34cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
35cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
36cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr    def start(self, test):
37cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        self.logfile = os.path.join(test.profdir, "perf")
3822434d4311581dde7a3bb51eef03a27d757aa263Eric Li        cmd = ("exec %s record -a -o %s" %
39d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li               (self.perf_bin, self.logfile))
4074a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        if "parent" in self.sort_keys:
4122434d4311581dde7a3bb51eef03a27d757aa263Eric Li            cmd += " -g"
4222434d4311581dde7a3bb51eef03a27d757aa263Eric Li        if self.trace:
4322434d4311581dde7a3bb51eef03a27d757aa263Eric Li            cmd += " -R"
44d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li        for event in self.events:
45d656d56473f50b9c1a9f5e2b2f5a9472181ee342Eric Li            cmd += " -e %s" % event
46cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        self._process = subprocess.Popen(cmd, shell=True,
47cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr                                         stderr=subprocess.STDOUT)
48cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
49cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
50cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr    def stop(self, test):
51cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        os.kill(self._process.pid, signal.SIGINT)
52cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr        self._process.wait()
53cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
54cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr
55cefc0f9eb9996bc9da9098a886e659c0578dbe00lmr    def report(self, test):
5674a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        for key in self.sort_keys:
5774a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            reportfile = os.path.join(test.profdir, '%s.comm' % key)
5874a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            cmd = ("%s report -i %s --sort %s,dso" % (self.perf_bin,
5974a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                                                      self.logfile,
6074a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                                                      key))
6174a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            outfile = open(reportfile, 'w')
6274a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            p = subprocess.Popen(cmd, shell=True, stdout=outfile,
6374a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                                 stderr=subprocess.STDOUT)
6474a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            p.wait()
6522434d4311581dde7a3bb51eef03a27d757aa263Eric Li
6674a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        if self.trace:
6774a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            tracefile = os.path.join(test.profdir, 'trace')
6874a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            cmd = ("%s script -i %s" % (self.perf_bin, self.logfile,))
6922434d4311581dde7a3bb51eef03a27d757aa263Eric Li
7074a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            outfile = open(tracefile, 'w')
7174a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            p = subprocess.Popen(cmd, shell=True, stdout=outfile,
7274a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                                 stderr=subprocess.STDOUT)
7374a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis            p.wait()
7422434d4311581dde7a3bb51eef03a27d757aa263Eric Li
7574a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        # The raw detailed perf output is HUGE.  We cannot store it by default.
7674a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        perf_log_size = os.stat(self.logfile)[stat.ST_SIZE]
7774a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        logging.info('Removing %s after generating reports (saving %s bytes).',
7874a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                     self.logfile, perf_log_size)
7974a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis        os.unlink(self.logfile)
80