xref: /freebsd/contrib/cortex-strings/scripts/plot-sizes.py (revision 8c4282b370bd66908b45b6a223226a9fc2b69d57)
1*09a53ad8SAndrew Turner#!/usr/bin/env python
2*09a53ad8SAndrew Turner
3*09a53ad8SAndrew Turner"""Plot the performance for different block sizes of one function across
4*09a53ad8SAndrew Turnervariants.
5*09a53ad8SAndrew Turner"""
6*09a53ad8SAndrew Turner
7*09a53ad8SAndrew Turnerimport libplot
8*09a53ad8SAndrew Turner
9*09a53ad8SAndrew Turnerimport pylab
10*09a53ad8SAndrew Turnerimport pdb
11*09a53ad8SAndrew Turnerimport math
12*09a53ad8SAndrew Turner
13*09a53ad8SAndrew Turnerdef pretty_kb(v):
14*09a53ad8SAndrew Turner    if v < 1024:
15*09a53ad8SAndrew Turner        return '%d' % v
16*09a53ad8SAndrew Turner    else:
17*09a53ad8SAndrew Turner        if v % 1024 == 0:
18*09a53ad8SAndrew Turner            return '%d k' % (v//1024)
19*09a53ad8SAndrew Turner        else:
20*09a53ad8SAndrew Turner            return '%.1f k' % (v/1024)
21*09a53ad8SAndrew Turner
22*09a53ad8SAndrew Turnerdef plot(records, function, alignment=None, scale=1):
23*09a53ad8SAndrew Turner    variants = libplot.unique(records, 'variant', prefer='this')
24*09a53ad8SAndrew Turner    records = [x for x in records if x.function==function]
25*09a53ad8SAndrew Turner
26*09a53ad8SAndrew Turner    if alignment != None:
27*09a53ad8SAndrew Turner        records = [x for x in records if x.src_alignment==alignment[0] and
28*09a53ad8SAndrew Turner                   x.dst_alignment==alignment[1]]
29*09a53ad8SAndrew Turner
30*09a53ad8SAndrew Turner    alignments = libplot.unique(records, ('src_alignment', 'dst_alignment'))
31*09a53ad8SAndrew Turner    if len(alignments) != 1:
32*09a53ad8SAndrew Turner        return False
33*09a53ad8SAndrew Turner    if libplot.alignments_equal(alignments):
34*09a53ad8SAndrew Turner        aalignment = alignments[0][0]
35*09a53ad8SAndrew Turner    else:
36*09a53ad8SAndrew Turner        aalignment = "%s:%s" % (alignments[0][0], alignments[0][1])
37*09a53ad8SAndrew Turner
38*09a53ad8SAndrew Turner    bytes = libplot.unique(records, 'bytes')[0]
39*09a53ad8SAndrew Turner
40*09a53ad8SAndrew Turner    colours = libplot.make_colours()
41*09a53ad8SAndrew Turner    all_x = []
42*09a53ad8SAndrew Turner
43*09a53ad8SAndrew Turner    pylab.figure(1).set_size_inches((6.4*scale, 4.8*scale))
44*09a53ad8SAndrew Turner    pylab.clf()
45*09a53ad8SAndrew Turner
46*09a53ad8SAndrew Turner    if 'str' in function:
47*09a53ad8SAndrew Turner        # The harness fills out to 16k.  Anything past that is an
48*09a53ad8SAndrew Turner        # early match
49*09a53ad8SAndrew Turner        top = 16384
50*09a53ad8SAndrew Turner    else:
51*09a53ad8SAndrew Turner        top = 2**31
52*09a53ad8SAndrew Turner
53*09a53ad8SAndrew Turner    for variant in variants:
54*09a53ad8SAndrew Turner        matches = [x for x in records if x.variant==variant and x.bytes <= top]
55*09a53ad8SAndrew Turner        matches.sort(key=lambda x: x.bytes)
56*09a53ad8SAndrew Turner
57*09a53ad8SAndrew Turner        X = sorted(list(set([x.bytes for x in matches])))
58*09a53ad8SAndrew Turner        Y = []
59*09a53ad8SAndrew Turner        Yerr = []
60*09a53ad8SAndrew Turner        for xbytes in X:
61*09a53ad8SAndrew Turner            vals = [x.bytes*x.loops/x.elapsed/(1024*1024) for x in matches if x.bytes == xbytes]
62*09a53ad8SAndrew Turner            if len(vals) > 1:
63*09a53ad8SAndrew Turner                mean = sum(vals)/len(vals)
64*09a53ad8SAndrew Turner                Y.append(mean)
65*09a53ad8SAndrew Turner                if len(Yerr) == 0:
66*09a53ad8SAndrew Turner                    Yerr = [[], []]
67*09a53ad8SAndrew Turner                err1 = max(vals) - mean
68*09a53ad8SAndrew Turner                assert err1 >= 0
69*09a53ad8SAndrew Turner                err2 = min(vals) - mean
70*09a53ad8SAndrew Turner                assert err2 <= 0
71*09a53ad8SAndrew Turner                Yerr[0].append(abs(err2))
72*09a53ad8SAndrew Turner                Yerr[1].append(err1)
73*09a53ad8SAndrew Turner            else:
74*09a53ad8SAndrew Turner                Y.append(vals[0])
75*09a53ad8SAndrew Turner
76*09a53ad8SAndrew Turner        all_x.extend(X)
77*09a53ad8SAndrew Turner        colour = colours.next()
78*09a53ad8SAndrew Turner
79*09a53ad8SAndrew Turner        if X:
80*09a53ad8SAndrew Turner            pylab.plot(X, Y, c=colour)
81*09a53ad8SAndrew Turner            if len(Yerr) > 0:
82*09a53ad8SAndrew Turner                pylab.errorbar(X, Y, yerr=Yerr, c=colour, label=variant, fmt='o')
83*09a53ad8SAndrew Turner            else:
84*09a53ad8SAndrew Turner                pylab.scatter(X, Y, c=colour, label=variant, edgecolors='none')
85*09a53ad8SAndrew Turner
86*09a53ad8SAndrew Turner    pylab.legend(loc='upper left', ncol=3, prop={'size': 'small'})
87*09a53ad8SAndrew Turner    pylab.grid()
88*09a53ad8SAndrew Turner    pylab.title('%(function)s of %(aalignment)s byte aligned blocks' % locals())
89*09a53ad8SAndrew Turner    pylab.xlabel('Size (B)')
90*09a53ad8SAndrew Turner    pylab.ylabel('Rate (MB/s)')
91*09a53ad8SAndrew Turner
92*09a53ad8SAndrew Turner    # Figure out how high the range goes
93*09a53ad8SAndrew Turner    top = max(all_x)
94*09a53ad8SAndrew Turner
95*09a53ad8SAndrew Turner    power = int(round(math.log(max(all_x)) / math.log(2)))
96*09a53ad8SAndrew Turner
97*09a53ad8SAndrew Turner    pylab.semilogx()
98*09a53ad8SAndrew Turner
99*09a53ad8SAndrew Turner    pylab.axes().set_xticks([2**x for x in range(0, power+1)])
100*09a53ad8SAndrew Turner    pylab.axes().set_xticklabels([pretty_kb(2**x) for x in range(0, power+1)])
101*09a53ad8SAndrew Turner    pylab.xlim(0, top)
102*09a53ad8SAndrew Turner    pylab.ylim(0, pylab.ylim()[1])
103*09a53ad8SAndrew Turner    return True
104*09a53ad8SAndrew Turner
105*09a53ad8SAndrew Turnerdef main():
106*09a53ad8SAndrew Turner    records = libplot.parse()
107*09a53ad8SAndrew Turner
108*09a53ad8SAndrew Turner    functions = libplot.unique(records, 'function')
109*09a53ad8SAndrew Turner    alignments = libplot.unique(records, ('src_alignment', 'dst_alignment'))
110*09a53ad8SAndrew Turner
111*09a53ad8SAndrew Turner    for function in functions:
112*09a53ad8SAndrew Turner        for alignment in alignments:
113*09a53ad8SAndrew Turner            for scale in [1, 2.5]:
114*09a53ad8SAndrew Turner                if plot(records, function, alignment, scale):
115*09a53ad8SAndrew Turner                    pylab.savefig('sizes-%s-%02d-%02d-%.1f.png' % (function, alignment[0], alignment[1], scale), dpi=72)
116*09a53ad8SAndrew Turner
117*09a53ad8SAndrew Turner    pylab.show()
118*09a53ad8SAndrew Turner
119*09a53ad8SAndrew Turnerif __name__ == '__main__':
120*09a53ad8SAndrew Turner    main()
121