]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cortex-strings/scripts/plot.py
MFC r340595-r340597
[FreeBSD/FreeBSD.git] / contrib / cortex-strings / scripts / plot.py
1 """Plot the results for each test.  Spits out a set of images into the
2 current directory.
3 """
4
5 import libplot
6
7 import fileinput
8 import collections
9 import pprint
10
11 import pylab
12
13 Record = collections.namedtuple('Record', 'variant test size loops src_alignment dst_alignment run_id rawtime comment time bytes rate')
14
15 def unique(rows, name):
16     """Takes a list of values, pulls out the named field, and returns
17     a list of the unique values of this field.
18     """
19     return sorted(set(getattr(x, name) for x in rows))
20
21 def to_float(v):
22     """Convert a string into a better type.
23
24     >>> to_float('foo')
25     'foo'
26     >>> to_float('1.23')
27     1.23
28     >>> to_float('45')
29     45
30     """
31     try:
32         if '.' in v:
33             return float(v)
34         else:
35             return int(v)
36     except:
37         return v
38
39 def parse():
40     # Split the input up
41     rows = [x.strip().split(':') for x in fileinput.input()]
42     # Automatically turn numbers into the base type
43     rows = [[to_float(y) for y in x] for x in rows]
44
45     # Scan once to calculate the overhead
46     r = [Record(*(x + [0, 0, 0])) for x in rows]
47     bounces = pylab.array([(x.loops, x.rawtime) for x in r if x.test == 'bounce'])
48     fit = pylab.polyfit(bounces[:,0], bounces[:,1], 1)
49
50     records = []
51
52     for row in rows:
53         # Make a dummy record so we can use the names
54         r1 = Record(*(row + [0, 0, 0]))
55
56         bytes = r1.size * r1.loops
57         # Calculate the bounce time
58         delta = pylab.polyval(fit, [r1.loops])
59         time = r1.rawtime - delta
60         rate = bytes / time
61
62         records.append(Record(*(row + [time, bytes, rate])))
63
64     return records
65
66 def plot(records, field, scale, ylabel):
67     variants = unique(records, 'variant')
68     tests = unique(records, 'test')
69
70     colours = libplot.make_colours()
71
72     # A little hack.  We want the 'all' record to be drawn last so
73     # that it's obvious on the graph.  Assume that no tests come
74     # before it alphabetically
75     variants.reverse()
76
77     for test in tests:
78         for variant in variants:
79             v = [x for x in records if x.test==test and x.variant==variant]
80             v.sort(key=lambda x: x.size)
81             V = pylab.array([(x.size, getattr(x, field)) for x in v])
82
83             # Ensure our results appear
84             order = 1 if variant == 'this' else 0
85
86             try:
87                 # A little hack.  We want the 'all' to be obvious on
88                 # the graph
89                 if variant == 'all':
90                     pylab.scatter(V[:,0], V[:,1]/scale, label=variant)
91                     pylab.plot(V[:,0], V[:,1]/scale)
92                 else:
93                     pylab.plot(V[:,0], V[:,1]/scale, label=variant,
94                             zorder=order, c = colours.next())
95
96             except Exception, ex:
97                 # michaelh1 likes to run this script while the test is
98                 # still running which can lead to bad data
99                 print ex, 'on %s of %s' % (variant, test)
100
101         pylab.legend(loc='lower right', ncol=2, prop={'size': 'small'})
102         pylab.xlabel('Block size (B)')
103         pylab.ylabel(ylabel)
104         pylab.title('%s %s' % (test, field))
105         pylab.grid()
106
107         pylab.savefig('%s-%s.png' % (test, field), dpi=100)
108         pylab.semilogx(basex=2)
109         pylab.savefig('%s-%s-semilog.png' % (test, field), dpi=100)
110         pylab.clf()
111
112 def test():
113     import doctest
114     doctest.testmod()
115
116 def main():
117     records = parse()
118
119     plot(records, 'rate', 1024**2, 'Rate (MB/s)')
120     plot(records, 'time', 1, 'Total time (s)')
121
122 if __name__ == '__main__':
123     main()