• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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