Counting profiler:

Counts cycles, instructions and computes CPI

Sampling profiler:

Uses perf record/report on a per-CPU basis

Signed-off-by: Arun Sharma <[email protected]>
---
 client/profilers/cpistat/control     |    3 +
 client/profilers/cpistat/cpistat     |   84 ++++++++++++++++++++++++++++++++++
 client/profilers/cpistat/cpistat.py  |   28 +++++++++++
 client/profilers/perf/control        |    3 +
 client/profilers/perf/perf.py        |   53 +++++++++++++++++++++
 5 files changed, 171 insertions(+), 0 deletions(-)
 create mode 100644 client/profilers/cpistat/__init__.py
 create mode 100644 client/profilers/cpistat/control
 create mode 100755 client/profilers/cpistat/cpistat
 create mode 100644 client/profilers/cpistat/cpistat.py
 create mode 100644 client/profilers/perf/__init__.py
 create mode 100644 client/profilers/perf/control
 create mode 100644 client/profilers/perf/perf.py

diff --git a/client/profilers/cpistat/__init__.py 
b/client/profilers/cpistat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/client/profilers/cpistat/control b/client/profilers/cpistat/control
new file mode 100644
index 0000000..7eac61e
--- /dev/null
+++ b/client/profilers/cpistat/control
@@ -0,0 +1,3 @@
+job.profilers.add('cpistat')
+job.run_test('sleeptest', seconds=10)
+job.profilers.delete('cpistat')
diff --git a/client/profilers/cpistat/cpistat b/client/profilers/cpistat/cpistat
new file mode 100755
index 0000000..e8aec06
--- /dev/null
+++ b/client/profilers/cpistat/cpistat
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+"""
+python-libpfm4 provides python bindings to the libpfm4
+library and the perf_event kernel subsystem. This
+script builds on them to provide a *stat like interface
+to CPU performance counters.
+
+Run as: ./cpistat -c cpulist -e eventlist
+
+Depends on libpfm4: http://perfmon2.sf.net/
+
+git://perfmon2.git.sourceforge.net/gitroot/perfmon2/libpfm4
+"""
+
+import sys, os, optparse, time, struct, perfmon
+
+if __name__ == '__main__':
+    parser = optparse.OptionParser()
+    parser.add_option('-e', '--events', help='Events to use',
+                       action='store', dest='events')
+    parser.add_option('-c', '--cpulist', help='CPUs to monitor',
+                       action='store', dest='cpulist')
+    parser.set_defaults(events='PERF_COUNT_HW_CPU_CYCLES,' +
+                               'PERF_COUNT_HW_INSTRUCTIONS')
+    (options, args) = parser.parse_args()
+
+    show_per_cpu = False
+    if not options.cpulist:
+        ncpus = os.sysconf('SC_NPROCESSORS_ONLN')
+        cpus = range(0, ncpus)
+    else:
+        cpus = options.cpulist.split(',')
+        cpus = [ int(c) for c in cpus ]
+        show_per_cpu = True
+
+    if options.events:
+        events = options.events.split(',')
+    else:
+        raise ValueError('You need to specify events to monitor')
+
+    s = perfmon.SystemWideSession(cpus, events)
+
+    s.start()
+    # Measuring loop
+    interval = 1
+    iters = -1
+    infinite = True
+    if len(args) == 2:
+        interval = int(args[0])
+        iters = int(args[1])
+        infinite = False
+
+    delta = {}
+    last = {}
+    sum = {}
+    for e in events:
+        delta[e] = {}
+        last[e] = {}
+        sum[e] = {}
+        for c in cpus:
+            delta[e][c] = 0
+            last[e][c] = 0
+
+    while infinite or iters:
+        for i in range(0, len(events)):
+          e = events[i]
+          sum[e] = 0
+          for c in cpus:
+              count = struct.unpack('L', s.read(c, i))[0]
+              delta[e][c] = count - last[e][c]
+              last[e][c] = count
+              if show_per_cpu:
+                  print '''CPU%d: %s\t%lu''' % (c, e, delta[e][c])
+              sum[e] += delta[e][c]
+
+        cycles = sum['PERF_COUNT_HW_CPU_CYCLES']
+        instructions = sum['PERF_COUNT_HW_INSTRUCTIONS']
+        CPI = cycles * 1.0/instructions
+        print ('cycles: %12lu, instructions: %12lu, CPI: %2.4f'
+               % (cycles, instructions, CPI))
+        sys.stdout.flush()
+        time.sleep(interval)
+        iters = iters - 1
diff --git a/client/profilers/cpistat/cpistat.py 
b/client/profilers/cpistat/cpistat.py
new file mode 100644
index 0000000..01524fb
--- /dev/null
+++ b/client/profilers/cpistat/cpistat.py
@@ -0,0 +1,28 @@
+"""
+Uses perf_events to count cycles and instructions
+
+Defaults options:
+job.profilers.add('cpistat', interval=1)
+"""
+import time, os, subprocess
+from autotest_lib.client.bin import profiler
+
+class cpistat(profiler.profiler):
+    version = 1
+
+    def initialize(self, interval = 1):
+        self.interval = interval
+
+
+    def start(self, test):
+        cmd = os.path.join(self.bindir, 'site_cpistat')
+        if not os.path.exists(cmd):
+           cmd = os.path.join(self.bindir, 'cpistat')
+        logfile = open(os.path.join(test.profdir, "cpistat"), 'w')
+        p = subprocess.Popen(cmd, stdout=logfile,
+                             stderr=subprocess.STDOUT)
+        self.pid = p.pid
+
+
+    def stop(self, test):
+        os.kill(self.pid, 15)
diff --git a/client/profilers/perf/__init__.py 
b/client/profilers/perf/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/client/profilers/perf/control b/client/profilers/perf/control
new file mode 100644
index 0000000..ed193d9
--- /dev/null
+++ b/client/profilers/perf/control
@@ -0,0 +1,3 @@
+job.profilers.add('perf')
+job.run_test('sleeptest', seconds=10)
+job.profilers.delete('perf')
diff --git a/client/profilers/perf/perf.py b/client/profilers/perf/perf.py
new file mode 100644
index 0000000..ff0a32e
--- /dev/null
+++ b/client/profilers/perf/perf.py
@@ -0,0 +1,53 @@
+"""
+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, subprocess, signal
+from autotest_lib.client.bin import profiler, os_dep, utils
+
+
+class perf(profiler.profiler):
+    version = 1
+
+    def initialize(self, events="cycles,instructions"):
+        self.events = events
+        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.strip(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 = ("%s record -a -o %s -e %s" %
+               (self.perf_bin, self.logfile, self.events))
+        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()
-- 
1.7.0.1

_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to