plot_sdcard.py revision 39c016f875b793296a121f41de5775b88f6fa1c9
139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#!/usr/bin/python2.5 239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania# 339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania# Copyright 2009 Google Inc. All Rights Reserved. 439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania"""plot_sdcard: A module to plot the results of an sdcard perf test. 639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 739c016f875b793296a121f41de5775b88f6fa1c9Nicolas CataniaRequires Gnuplot python v 1.8 839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 939c016f875b793296a121f41de5775b88f6fa1c9Nicolas CataniaTypical usage: 1039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 1139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniapython 1239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania>>> import plot_sdcard as p 1339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania>>> (metadata, data) = p.parse('/tmp/data.txt') 1439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania>>> p.plotIterations(metadata, data) 1539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania>>> p.plotTimes(metadata, data) 1639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 1739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania""" 1839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 1939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#TODO: provide a main so we can pipe the result from the run 2039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#TODO: more comments... 2139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 2239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaimport Gnuplot 2339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniafrom numpy import * 2439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaimport sys 2539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaimport re 2639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniafrom itertools import izip 2739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 2839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaclass DataSet(object): 2939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def __init__(self, line): 3039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania res = re.search('# StopWatch ([\w]+) total/cumulative duration ([0-9.]+)\. Samples: ([0-9]+)', line) 3139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.time = [] 3239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.data = [] 3339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.name = res.group(1) 3439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.duration = float(res.group(2)) 3539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.iteration = int(res.group(3)) 3639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania print "Name: %s Duration: %f Iterations: %d" % (self.name, self.duration, self.iteration) 3739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.summary = re.match('([a-z_]+)_total', self.name) 3839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 3939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def __repr__(self): 4039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania return str(zip(self.time, self.data)) 4139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 4239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def add(self, time, value): 4339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.time.append(time) 4439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.data.append(value) 4539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 4639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def rescaleTo(self, length): 4739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania factor = len(self.data) / length 4839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 4939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if factor > 1: 5039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania new_time = [] 5139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania new_data = [] 5239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania accum = 0.0 5339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania idx = 1 5439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania for t,d in izip(self.time, self.data): 5539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania accum += d 5639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if idx % factor == 0: 5739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania new_time.append(t) 5839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania new_data.append(accum / factor) 5939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania accum = 0 6039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania idx += 1 6139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.time = new_time 6239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.data = new_data 6339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 6439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 6539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaclass Metadata(object): 6639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def __init__(self): 6739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.kernel = '' 6839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.command_line = '' 6939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.sched = '' 7039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.name = '' 7139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.fadvise = '' 7239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.iterations = 0 7339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.duration = 0.0 7439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.complete = False 7539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 7639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def parse(self, line): 7739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if line.startswith('# Kernel:'): 7839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.kernel = re.search('Linux version ([0-9.]+-[0-9]+)', line).group(1) 7939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania elif line.startswith('# Command:'): 8039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.command_line = re.search('# Command: [/\w_]+ (.*)', line).group(1) 8139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.command_line = self.command_line.replace(' --', '-') 8239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.command_line = self.command_line.replace(' -d', '') 8339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.command_line = self.command_line.replace('--test=', '') 8439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania elif line.startswith('# Iterations'): 8539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.iterations = int(re.search('# Iterations: ([0-9]+)', line).group(1)) 8639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania elif line.startswith('# Fadvise'): 8739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.fadvise = int(re.search('# Fadvise: ([\w]+)', line).group(1)) 8839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania elif line.startswith("# Sched"): 8939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.sched = re.search('# Sched features: ([\w]+)', line).group(1) 9039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.complete = True 9139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 9239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def asTitle(self): 9339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania return "%s-duration:%f\\n-%s\\n%s" % (self.kernel, self.duration, self.command_line, self.sched) 9439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 9539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania def updateWith(self, dataset): 9639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.duration = max(self.duration, dataset.duration) 9739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania self.name = dataset.name 9839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 9939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 10039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniadef plotIterations(metadata, data): 10139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp = Gnuplot.Gnuplot(persist = 1) 10239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp('set data style lines') 10339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.clear() 10439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.xlabel("iterations") 10539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.ylabel("duration in second") 10639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.title(metadata.asTitle()) 10739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania styles = {} 10839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania line_style = 1 10939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 11039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania for dataset in data: 11139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania dataset.rescaleTo(metadata.iterations) 11239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania x = arange(len(dataset.data), dtype='int_') 11339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if not dataset.name in styles: 11439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania styles[dataset.name] = line_style 11539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania line_style += 1 11639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania d = Gnuplot.Data(x, dataset.data, 11739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania title=dataset.name, 11839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania with_='lines ls %d' % styles[dataset.name]) 11939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania else: # no need to repeat a title that exists already. 12039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania d = Gnuplot.Data(x, dataset.data, 12139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania with_='lines ls %d' % styles[dataset.name]) 12239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 12339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.replot(d) 12439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') 12539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 12639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniadef plotTimes(metadata, data): 12739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp = Gnuplot.Gnuplot(persist = 1) 12839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp('set data style impulses') 12939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp('set xtics 1') 13039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.clear() 13139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.xlabel("seconds") 13239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.ylabel("duration in second") 13339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.title(metadata.asTitle()) 13439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania styles = {} 13539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania line_style = 1 13639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 13739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania for dataset in data: 13839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania #dataset.rescaleTo(metadata.iterations) 13939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania x = array(dataset.time, dtype='float_') 14039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if not dataset.name in styles: 14139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania styles[dataset.name] = line_style 14239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania line_style += 1 14339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania d = Gnuplot.Data(x, dataset.data, 14439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania title=dataset.name, 14539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania with_='impulses ls %d' % styles[dataset.name]) 14639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania else: # no need to repeat a title that exists already. 14739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania d = Gnuplot.Data(x, dataset.data, 14839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania with_='impulses ls %d' % styles[dataset.name]) 14939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 15039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.replot(d) 15139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania gp.hardcopy('/tmp/%s-%s-%f.png' % (metadata.name, metadata.kernel, metadata.duration), terminal='png') 15239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 15339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 15439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniadef parse(filename): 15539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania f = open(filename, 'r') 15639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 15739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania metadata = Metadata() 15839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania data = [] # array of dataset 15939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania dataset = None 16039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 16139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania for num, line in enumerate(f): 16239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania try: 16339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania line = line.strip() 16439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if not line: continue 16539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 16639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if not metadata.complete: 16739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania metadata.parse(line) 16839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania continue 16939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 17039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if re.match('[a-z_]', line): 17139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania continue 17239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 17339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if line.startswith('# StopWatch'): # Start of a new dataset 17439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if dataset: 17539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if dataset.summary: 17639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania metadata.updateWith(dataset) 17739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania else: 17839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania data.append(dataset) 17939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 18039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania dataset = DataSet(line) 18139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania continue 18239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 18339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if line.startswith('#'): 18439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania continue 18539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 18639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania # must be data at this stage 18739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania try: 18839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania (time, value) = line.split(None, 1) 18939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania except ValueError: 19039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania print "skipping line %d: %s" % (num, line) 19139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania continue 19239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 19339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania if dataset and not dataset.summary: 19439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania dataset.add(float(time), float(value)) 19539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania 19639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania except Exception, e: 19739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania print "Error parsing line %d" % num, sys.exc_info()[0] 19839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania raise 19939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania data.append(dataset) 20039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania return (metadata, data) 201