On Tue, Jun 22, 2010 at 2:34 PM, Lucas Meneghel Rodrigues
<[email protected]> wrote:
> Could you send a full patch against the latest trunk please?

Certainly. As attached.

 -Arun
From 7b81c36c072074612c096a608fa2e347a67960a1 Mon Sep 17 00:00:00 2001
From: Arun Sharma <[email protected]>
Date: Tue, 22 Jun 2010 14:42:59 -0700
Subject: [PATCH] Add perf_events based counting/sampling profilers to autotest

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       |   42 +++++++++++++++++
 5 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100644 client/profilers/cpistat/control
 create mode 100644 client/profilers/cpistat/cpistat
 create mode 100644 client/profilers/cpistat/cpistat.py
 create mode 100644 client/profilers/perf/control
 create mode 100644 client/profilers/perf/perf.py

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 100644
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/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..8f5eb44
--- /dev/null
+++ b/client/profilers/perf/perf.py
@@ -0,0 +1,42 @@
+"""
+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
+
+class perf(profiler.profiler):
+    version = 1
+
+    def initialize(self, events="cycles,instructions"):
+        self.events = events
+
+
+    def start(self, test):
+        self.logfile = os.path.join(test.profdir, "perf")
+        cmd = ("/usr/bin/perf record -a -o %s -e %s" %
+               (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):
+        self.reportfile_comm = os.path.join(test.profdir, 'perf.comm')
+        cmd = "/usr/bin/perf report -i %s --sort comm,dso" % self.logfile
+        outfile = open(self.reportfile_comm, 'w')
+        p1 = subprocess.Popen(cmd, shell=True, stdout=outfile,
+                              stderr=subprocess.STDOUT)
+        p1.wait()
+        self.reportfile_cpu = os.path.join(test.profdir, 'perf.cpu')
+        cmd = "/usr/bin/perf report -i %s --sort cpu,dso" % self.logfile
+        outfile = open(self.reportfile_cpu, 'w')
+        p2 = subprocess.Popen(cmd, shell=True, stdout=outfile,
+                              stderr=subprocess.STDOUT)
+        p2.wait()
-- 
1.7.0.4

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

Reply via email to