1"""Plot the results for each test. Spits out a set of images into the 2current directory. 3""" 4 5import libplot 6 7import fileinput 8import collections 9import pprint 10 11import pylab 12 13Record = collections.namedtuple('Record', 'variant test size loops src_alignment dst_alignment run_id rawtime comment time bytes rate') 14 15def 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 21def 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 39def 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 66def 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 112def test(): 113 import doctest 114 doctest.testmod() 115 116def main(): 117 records = parse() 118 119 plot(records, 'rate', 1024**2, 'Rate (MB/s)') 120 plot(records, 'time', 1, 'Total time (s)') 121 122if __name__ == '__main__': 123 main() 124