Home | History | Annotate | Download | only in perf
      1 """
      2 perf is a tool included in the linux kernel tree that
      3 supports functionality similar to oprofile and more.
      4 
      5 @see: http://lwn.net/Articles/310260/
      6 """
      7 
      8 import time, os, stat, subprocess, signal
      9 import logging
     10 from autotest_lib.client.bin import profiler, os_dep, utils
     11 
     12 
     13 class 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