09a53ad8f1
Sponsored by: The FreeBSD Foundation
124 lines
3.5 KiB
Python
124 lines
3.5 KiB
Python
"""Plot the results for each test. Spits out a set of images into the
|
|
current directory.
|
|
"""
|
|
|
|
import libplot
|
|
|
|
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')
|
|
|
|
colours = libplot.make_colours()
|
|
|
|
# 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, c = colours.next())
|
|
|
|
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()
|