1#!/usr/bin/python2.7 2# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import itertools 7import subprocess 8import sys 9 10import numpy 11 12import stats_utils 13 14 15class Error(Exception): 16 """Module error class.""" 17 18 19def GatherPerfStats(program, events, multiplier=1000, 20 progress_func=lambda i, j: None): 21 """Run perf stat with the given events and given program. 22 23 @param program: path to benchmark binary. It should take one argument 24 (number of loop iterations) and produce no output. 25 @param events: value to pass to '-e' arg of perf stat. 26 @param multiplier: loop multiplier 27 @param progress_func: function that tracks progress of running the 28 benchmark. takes two arguments for the outer and inner iteration 29 numbers. 30 @returns: List of dicts. 31 """ 32 facts = [] 33 for i, j in itertools.product(xrange(10), xrange(5)): 34 progress_func(i, j) 35 loops = (i+1) * multiplier 36 out = subprocess.check_output( 37 ('perf', 'stat', '-x', ',', 38 '-e', events, 39 program, '%d' % loops), 40 stderr=subprocess.STDOUT) 41 unsupported_events = [] 42 f = {'loops': loops} 43 for line in out.splitlines(): 44 fields = line.split(',') 45 count, unit, event = None, None, None 46 if len(fields) == 2: 47 count, event = fields 48 elif len(fields) == 3: 49 count, unit, event = fields 50 else: 51 raise Error('Unable to parse perf stat output') 52 if count == '<not supported>': 53 unsupported_events.append(event) 54 else: 55 f[event] = int(count) 56 if unsupported_events: 57 raise Error('These events are not supported: %s' 58 % unsupported_events) 59 facts.append(f) 60 progress_func(-1, -1) # Finished 61 return facts 62 63 64def main(): 65 """This can be run stand-alone.""" 66 def _Progress(i, j): 67 if i == -1 and j == -1: # Finished 68 print 69 return 70 if j == 0: 71 if i != 0: 72 print 73 print i, ':', 74 print j, 75 sys.stdout.flush() 76 77 events = ('cycles', 'instructions') 78 facts = GatherPerfStats('src/noploop', ','.join(events), 79 multiplier=10*1000*1000, progress_func=_Progress) 80 81 dt = numpy.dtype([('loops', numpy.int)] + 82 [(e, numpy.int) for e in events]) 83 a = stats_utils.FactsToNumpyArray(facts, dt) 84 for y_var in events: 85 print y_var 86 (slope, intercept), r2 = stats_utils.LinearRegression( 87 a['loops'], a[y_var]) 88 print "slope:", slope 89 print "intercept:", intercept 90 print "r-squared:", r2 91 92 93if __name__ == '__main__': 94 main() 95