# Copyright (c) 2005 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer; # redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution; # neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from orderdict import orderdict import output class ProfileData(object): def __init__(self): self.data = {} self.total = {} self.runs = orderdict() self.runlist = [] def addvalue(self, run, cpu, symbol, value): value = float(value) self.data[run, cpu, symbol] = self.getvalue(run, cpu, symbol) + value self.total[run, cpu] = self.gettotal(run, cpu) + value if run not in self.runs: self.runs[run] = orderdict() if cpu not in self.runs[run]: self.runs[run][cpu] = {} if symbol not in self.runs[run][cpu]: self.runs[run][cpu][symbol] = 0 self.runs[run][cpu][symbol] += value def getvalue(self, run, cpu, symbol): return self.data.get((run, cpu, symbol), 0) def gettotal(self, run, cpu): return self.total.get((run, cpu), 0) class Profile(object): default_order = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp'] # This list controls the order of values in stacked bar data output default_categories = [ 'interrupt', 'driver', 'stack', 'bufmgt', 'copy', 'user', 'other', 'idle'] def __init__(self, run_order=[], categories=[], stacknames=[]): if not run_order: run_order = Profile.default_order if not categories: categories = Profile.default_categories self.run_order = run_order self.categories = categories self.rcategories = [] self.rcategories.extend(categories) self.rcategories.reverse() self.stacknames = stacknames self.prof = ProfileData() self.categorize = True self.showidle = True self.maxsymlen = 0 def category(self, symbol): from categories import categories, categories_re if categories.has_key(symbol): return categories[symbol] for regexp, cat in categories_re: if regexp.match(symbol): return cat return 'other' # Parse input file and put the results in the given run and cpu def parsefile(self, run, cpu, filename): fd = file(filename) for line in fd: (symbol, count) = line.split() if symbol == "0x0": continue count = int(count) if self.categorize: symbol = self.category(symbol) if symbol == 'idle' and not self.showidle: continue if symbol not in self.categories: symbol = 'other' self.maxsymlen = max(self.maxsymlen, len(symbol)) self.prof.addvalue(run, cpu, symbol, count) fd.close() # Read in files def inputdir(self, directory): import os, os.path, re from os.path import expanduser, join as joinpath directory = expanduser(directory) label_ex = re.compile(r'm5prof\.(.*)') for root,dirs,files in os.walk(directory): for name in files: match = label_ex.match(name) if not match: continue filename = joinpath(root, name) prefix = os.path.commonprefix([root, directory]) dirname = root[len(prefix)+1:] self.parsefile(dirname, match.group(1), filename) def get(self, job, stat): if job.system is None: raise AttributeError, 'The job must have a system set' cpu = '%s.full0' % job.system values = [] for cat in self.categories: values.append(self.prof.getvalue(job.name, cpu, cat)) return values