blob: e8aec06cb2e3c71653959f1e04e2acf8334a6c7b [file] [log] [blame]
#!/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