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