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
