profile.py revision 1881:fc205a7edd58
1# Copyright (c) 2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution; 11# neither the name of the copyright holders nor the names of its 12# contributors may be used to endorse or promote products derived from 13# this software without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27from orderdict import orderdict 28import output 29 30class ProfileData(object): 31 def __init__(self): 32 self.data = {} 33 self.total = {} 34 self.runs = orderdict() 35 self.runlist = [] 36 37 def addvalue(self, run, cpu, symbol, value): 38 value = float(value) 39 self.data[run, cpu, symbol] = self.getvalue(run, cpu, symbol) + value 40 self.total[run, cpu] = self.gettotal(run, cpu) + value 41 if run not in self.runs: 42 self.runs[run] = orderdict() 43 44 if cpu not in self.runs[run]: 45 self.runs[run][cpu] = {} 46 47 if symbol not in self.runs[run][cpu]: 48 self.runs[run][cpu][symbol] = 0 49 50 self.runs[run][cpu][symbol] += value 51 52 def getvalue(self, run, cpu, symbol): 53 return self.data.get((run, cpu, symbol), 0) 54 55 def gettotal(self, run, cpu): 56 return self.total.get((run, cpu), 0) 57 58class Profile(object): 59 default_order = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp'] 60 61 # This list controls the order of values in stacked bar data output 62 default_categories = [ 'interrupt', 63 'driver', 64 'stack', 65 'bufmgt', 66 'copy', 67 'user', 68 'other', 69 'idle'] 70 71 def __init__(self, run_order=[], categories=[], stacknames=[]): 72 if not run_order: 73 run_order = Profile.default_order 74 if not categories: 75 categories = Profile.default_categories 76 77 self.run_order = run_order 78 self.categories = categories 79 self.rcategories = [] 80 self.rcategories.extend(categories) 81 self.rcategories.reverse() 82 self.stacknames = stacknames 83 self.prof = ProfileData() 84 self.categorize = True 85 self.showidle = True 86 self.maxsymlen = 0 87 88 def category(self, symbol): 89 from categories import categories, categories_re 90 if categories.has_key(symbol): 91 return categories[symbol] 92 for regexp, cat in categories_re: 93 if regexp.match(symbol): 94 return cat 95 return 'other' 96 97 # Parse input file and put the results in the given run and cpu 98 def parsefile(self, run, cpu, filename): 99 fd = file(filename) 100 101 for line in fd: 102 (symbol, count) = line.split() 103 if symbol == "0x0": 104 continue 105 count = int(count) 106 107 if self.categorize: 108 symbol = self.category(symbol) 109 if symbol == 'idle' and not self.showidle: 110 continue 111 112 if symbol not in self.categories: 113 symbol = 'other' 114 115 self.maxsymlen = max(self.maxsymlen, len(symbol)) 116 self.prof.addvalue(run, cpu, symbol, count) 117 118 fd.close() 119 120 # Read in files 121 def inputdir(self, directory): 122 import os, os.path, re 123 from os.path import expanduser, join as joinpath 124 125 directory = expanduser(directory) 126 label_ex = re.compile(r'm5prof\.(.*)') 127 for root,dirs,files in os.walk(directory): 128 for name in files: 129 match = label_ex.match(name) 130 if not match: 131 continue 132 133 filename = joinpath(root, name) 134 prefix = os.path.commonprefix([root, directory]) 135 dirname = root[len(prefix)+1:] 136 self.parsefile(dirname, match.group(1), filename) 137 138 def get(self, job, stat): 139 if job.system is None: 140 raise AttributeError, 'The job must have a system set' 141 142 cpu = '%s.full0' % job.system 143 values = [] 144 for cat in self.categories: 145 values.append(self.prof.getvalue(job.name, cpu, cat)) 146 return values 147