~linaro-toolchain-dev/cortex-strings/trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""Plot the results for each test.  Spits out a set of images into the
current directory.
"""

import fileinput
import collections
import pprint

import pylab

Record = collections.namedtuple('Record', 'variant test size loops src_alignment dst_alignment run_id rawtime comment time bytes rate')

def unique(rows, name):
    """Takes a list of values, pulls out the named field, and returns
    a list of the unique values of this field.
    """
    return sorted(set(getattr(x, name) for x in rows))

def to_float(v):
    """Convert a string into a better type.

    >>> to_float('foo')
    'foo'
    >>> to_float('1.23')
    1.23
    >>> to_float('45')
    45
    """
    try:
        if '.' in v:
            return float(v)
        else:
            return int(v)
    except:
        return v

def parse():
    # Split the input up
    rows = [x.strip().split(':') for x in fileinput.input()]
    # Automatically turn numbers into the base type
    rows = [[to_float(y) for y in x] for x in rows]

    # Scan once to calculate the overhead
    r = [Record(*(x + [0, 0, 0])) for x in rows]
    bounces = pylab.array([(x.loops, x.rawtime) for x in r if x.test == 'bounce'])
    fit = pylab.polyfit(bounces[:,0], bounces[:,1], 1)

    records = []

    for row in rows:
        # Make a dummy record so we can use the names
        r1 = Record(*(row + [0, 0, 0]))

        bytes = r1.size * r1.loops
        # Calculate the bounce time
        delta = pylab.polyval(fit, [r1.loops])
        time = r1.rawtime - delta
        rate = bytes / time

        records.append(Record(*(row + [time, bytes, rate])))

    return records

def plot(records, field, scale, ylabel):
    variants = unique(records, 'variant')
    tests = unique(records, 'test')

    # A little hack.  We want the 'all' record to be drawn last so
    # that it's obvious on the graph.  Assume that no tests come
    # before it alphabetically
    variants.reverse()

    for test in tests:
        for variant in variants:
            v = [x for x in records if x.test==test and x.variant==variant]
            v.sort(key=lambda x: x.size)
            V = pylab.array([(x.size, getattr(x, field)) for x in v])

            # Ensure our results appear
            order = 1 if variant == 'this' else 0

            try:
                # A little hack.  We want the 'all' to be obvious on
                # the graph
                if variant == 'all':
                    pylab.scatter(V[:,0], V[:,1]/scale, label=variant)
                    pylab.plot(V[:,0], V[:,1]/scale)
                else:
                    pylab.plot(V[:,0], V[:,1]/scale, label=variant, zorder=order)

            except Exception, ex:
                # michaelh1 likes to run this script while the test is
                # still running which can lead to bad data
                print ex, 'on %s of %s' % (variant, test)

        pylab.legend(loc='lower right', ncol=2, prop={'size': 'small'})
        pylab.xlabel('Block size (B)')
        pylab.ylabel(ylabel)
        pylab.title('%s %s' % (test, field))
        pylab.grid()

        pylab.savefig('%s-%s.png' % (test, field), dpi=100)
        pylab.semilogx(basex=2)
        pylab.savefig('%s-%s-semilog.png' % (test, field), dpi=100)
        pylab.clf()

def test():
    import doctest
    doctest.testmod()

def main():
    records = parse()

    plot(records, 'rate', 1024**2, 'Rate (MB/s)')
    plot(records, 'time', 1, 'Total time (s)')

if __name__ == '__main__':
    main()