Major improvements in the graph output code. Mostly adding more

options, making existing options more visible and dealing with
holes in data better.

util/stats/barchart.py:
    - move the options for BarChart to a base class ChartOptions so
    they can be more easily set and copied.
    - add an option to set the chart size (so you can adjust the aspect ratio)
    - don't do the add_subplot thing, use add_axes directly so we can
    affect the size of the figure itself to make room for the legend
    - make the initial array bottom floating point so we don't lose precision
    - add an option to set the limits on the y axis
    - use a figure legend instead of an axes legend so we can put the legend
    outside of the actual chart.  Also add an option to set the fontsize of
    the legend.
    - initial hack at outputting csv files
util/stats/db.py:
    don't print out an error when the run is missing from the database
    just return None, the error will be print elsewhere.
util/stats/output.py:
    - make StatOutput derive from ChartOptions so that it's easier to
    set default chart options.
    - make the various output functions (graph, display, etc.) take the
    name of the data as a parameter instead of making it a parameter to
    __init__.  This allows me to create the StatOutput object with
    generic parameters while still being able to specialize the name
    after the fact
    - add support for graph_group and graph_bars to be applied to multiple
    configuration groups.  This results in a cross product of the groups
    to be generated and used.
    - flush the html file output as we go so that we can load the file
    while graphs are still being generated.
    - make the proxy a parameter to the graph function so the proper system's
    data can be graphed
    - for any groups or bars that are completely missing, remove them from
    the graph.  This way, if we decide not to do a set of runs, there won't
    be holes in the data.
    - output eps and ps by default in addition to the png.
util/stats/profile.py:
    - clean up the data structures that are used to store the function
    profile information and try our best to avoid keeping extra data
    around that isn't used.
    - make get() return None if a job is missing so we know it was
    missing rather than the all zeroes thing.
    - make the function profile categorization stuff total up to 100%
    - Fixup the x-axis and y-axis labels.
    - fix the dot file output stuff.
util/stats/stats.py:
    support the new options stuff for StatOutput

--HG--
extra : convert_revision : fae35df8c57a36257ea93bc3e0a0e617edc46bb7
This commit is contained in:
Nathan Binkert 2005-11-22 21:50:34 -05:00
parent 7819ca6b97
commit c0a4836077
6 changed files with 297 additions and 146 deletions

View file

@ -28,28 +28,19 @@
# Lisa Hsu
import matplotlib, pylab
from matplotlib.font_manager import FontProperties
from matplotlib.numerix import array, arange, reshape, shape, transpose, zeros
from matplotlib.numerix import Float
matplotlib.interactive(False)
class BarChart(object):
def __init__(self, **kwargs):
self.init(**kwargs)
from chart import ChartOptions
def init(self, **kwargs):
self.colormap = 'jet'
class BarChart(ChartOptions):
def __init__(self, default=None, **kwargs):
super(BarChart, self).__init__(default, **kwargs)
self.inputdata = None
self.chartdata = None
self.xlabel = None
self.ylabel = None
self.legend = None
self.xticks = None
self.yticks = None
self.title = None
for key,value in kwargs.iteritems():
self.__setattr__(key, value)
def gen_colors(self, count):
cmap = matplotlib.cm.get_cmap(self.colormap)
@ -129,8 +120,8 @@ class BarChart(object):
if self.chartdata is None:
raise AttributeError, "Data not set for bar chart!"
self.figure = pylab.figure()
self.axes = self.figure.add_subplot(111)
self.figure = pylab.figure(figsize=self.chart_size)
self.axes = self.figure.add_axes(self.figure_size)
dim = len(shape(self.inputdata))
cshape = shape(self.chartdata)
@ -158,7 +149,7 @@ class BarChart(object):
bars = []
for i,stackdata in enumerate(self.chartdata):
bottom = array([0] * len(stackdata[0]))
bottom = array([0.0] * len(stackdata[0]), Float)
stack = []
for j,bardata in enumerate(stackdata):
bardata = array(bardata)
@ -181,6 +172,8 @@ class BarChart(object):
ticks = arange(nticks) / (nticks - 1) * (ymax - ymin) + ymin
self.axes.set_yticks(ticks)
self.axes.set_yticklabels(self.yticks)
elif self.ylim is not None:
self.axes.set_ylim(self.ylim)
if self.xticks is not None:
self.axes.set_xticks(arange(cshape[2]) + .5)
@ -195,7 +188,8 @@ class BarChart(object):
number = len(bars[0])
lbars = [ bars[0][number - j - 1][0] for j in xrange(number)]
self.axes.legend(lbars, self.legend, loc='best')
self.figure.legend(lbars, self.legend, self.legend_loc,
prop=FontProperties(size=self.legend_size))
if self.title is not None:
self.axes.set_title(self.title)
@ -203,7 +197,32 @@ class BarChart(object):
def savefig(self, name):
self.figure.savefig(name)
def savecsv(self, name):
f = file(name, 'w')
data = array(self.inputdata)
dim = len(data.shape)
if dim == 1:
#if self.xlabel:
# f.write(', '.join(list(self.xlabel)) + '\n')
f.write(', '.join([ '%f' % val for val in data]) + '\n')
if dim == 2:
#if self.xlabel:
# f.write(', '.join([''] + list(self.xlabel)) + '\n')
for i,row in enumerate(data):
ylabel = []
#if self.ylabel:
# ylabel = [ self.ylabel[i] ]
f.write(', '.join(ylabel + [ '%f' % val for val in row]) + '\n')
if dim == 3:
f.write("don't do 3D csv files\n")
pass
f.close()
if __name__ == '__main__':
from random import randrange
import random, sys
dim = 3
@ -234,13 +253,17 @@ if __name__ == '__main__':
chart1.xticks = [ 'xtick%d' % x for x in xrange(myshape[0]) ]
chart1.title = 'this is the title'
chart1.graph()
#chart1.savefig('/tmp/test1.png')
chart1.savefig('/tmp/test1.png')
chart1.savefig('/tmp/test1.ps')
chart1.savefig('/tmp/test1.eps')
chart1.savecsv('/tmp/test1.csv')
if False:
chart2 = BarChart()
chart2.data = data
chart2.colormap = 'gray'
chart2.graph()
#chart2.savefig('/tmp/test2.png')
chart2.savefig('/tmp/test2.png')
chart2.savefig('/tmp/test2.ps')
pylab.show()
#pylab.show()

84
util/stats/chart.py Normal file
View file

@ -0,0 +1,84 @@
# 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.
#
# Authors: Nathan Binkert
# Lisa Hsu
class ChartOptions(object):
defaults = { 'chart_size' : (8, 4),
'figure_size' : [0.1, 0.1, 0.6, 0.85],
'title' : None,
'legend' : None,
'legend_loc' : 'upper right',
'legend_size' : 6,
'colormap' : 'jet',
'xlabel' : None,
'ylabel' : None,
'xticks' : None,
'yticks' : None,
'ylim' : None,
}
def __init__(self, options=None, **kwargs):
self.init(options, **kwargs)
def clear(self):
self.options = {}
def init(self, options=None, **kwargs):
self.clear()
self.update(options, **kwargs)
def update(self, options=None, **kwargs):
if options is not None:
if not isinstance(options, ChartOptions):
raise AttributeError, \
'attribute options of type %s should be %s' % \
(type(options), ChartOptions)
self.options.update(options.options)
for key,value in kwargs.iteritems():
if key not in ChartOptions.defaults:
raise AttributeError, \
"%s instance has no attribute '%s'" % (type(self), key)
self.options[key] = value
def __getattr__(self, attr):
if attr in self.options:
return self.options[attr]
if attr in ChartOptions.defaults:
return ChartOptions.defaults[attr]
raise AttributeError, \
"%s instance has no attribute '%s'" % (type(self), attr)
def __setattr__(self, attr, value):
if attr in ChartOptions.defaults:
self.options[attr] = value
else:
super(ChartOptions, self).__setattr__(attr, value)

View file

@ -155,7 +155,6 @@ class Database(object):
def get(self, job, stat):
run = self.allRunNames.get(job.name, None)
if run is None:
print 'run "%s" not found' % job
return None
from info import scalar, vector, value, values, total, len

View file

@ -26,21 +26,22 @@
#
# Authors: Nathan Binkert
class StatOutput(object):
def __init__(self, name, jobfile, info, stat=None, binstats=None):
self.name = name
from chart import ChartOptions
class StatOutput(ChartOptions):
def __init__(self, jobfile, info, stat=None, binstats=None):
super(StatOutput, self).__init__()
self.jobfile = jobfile
self.stat = stat
self.binstats = None
self.label = self.name
self.invert = False
self.info = info
def printdata(self, bin = None, printmode = 'G'):
def printdata(self, name, bin = None, printmode = 'G'):
import info
if bin:
print '%s %s stats' % (self.name, bin)
print '%s %s stats' % (name, bin)
if self.binstats:
for stat in self.binstats:
@ -69,70 +70,78 @@ class StatOutput(object):
valstring = ', '.join([ valformat % val for val in value ])
print '%-50s %s' % (job.name + ':', valstring)
def display(self, binned = False, printmode = 'G'):
def display(self, name, binned = False, printmode = 'G'):
if binned and self.binstats:
self.printdata('kernel', printmode)
self.printdata('idle', printmode)
self.printdata('user', printmode)
self.printdata('interrupt', printmode)
self.printdata(name, 'kernel', printmode)
self.printdata(name, 'idle', printmode)
self.printdata(name, 'user', printmode)
self.printdata(name, 'interrupt', printmode)
print '%s total stats' % self.name
self.printdata(printmode=printmode)
print '%s total stats' % name
self.printdata(name, printmode=printmode)
def graph(self, graphdir):
def graph(self, name, graphdir, proxy=None):
from os.path import expanduser, isdir, join as joinpath
from barchart import BarChart
from matplotlib.numerix import Float, array, zeros
import os, re
import os, re, urllib
from jobfile import crossproduct
confgroups = self.jobfile.groups()
ngroups = len(confgroups)
skiplist = [ False ] * ngroups
groupopts = None
baropts = None
groupopts = []
baropts = []
groups = []
for i,group in enumerate(confgroups):
if group.flags.graph_group:
if groupopts is not None:
raise AttributeError, \
'Two groups selected for graph group'
groupopts = group.subopts()
groupopts.append(group.subopts())
skiplist[i] = True
elif group.flags.graph_bars:
if baropts is not None:
raise AttributeError, \
'Two groups selected for graph bars'
baropts = group.subopts()
baropts.append(group.subopts())
skiplist[i] = True
else:
groups.append(group)
if groupopts is None:
if not groupopts:
raise AttributeError, 'No group selected for graph group'
if baropts is None:
if not baropts:
raise AttributeError, 'No group selected for graph bars'
groupopts = [ group for group in crossproduct(groupopts) ]
baropts = [ bar for bar in crossproduct(baropts) ]
directory = expanduser(graphdir)
if not isdir(directory):
os.mkdir(directory)
html = file(joinpath(directory, '%s.html' % self.name), 'w')
html = file(joinpath(directory, '%s.html' % name), 'w')
print >>html, '<html>'
print >>html, '<title>Graphs for %s</title>' % self.name
print >>html, '<title>Graphs for %s</title>' % name
print >>html, '<body>'
html.flush()
for options in self.jobfile.options(groups):
chart = BarChart(self)
data = zeros((len(groupopts), len(baropts)), Float)
data = [ [ None ] * len(baropts) for i in xrange(len(groupopts)) ]
enabled = False
stacked = 0
for g,gopt in enumerate(groupopts):
for b,bopt in enumerate(baropts):
job = self.jobfile.job(options + [ gopt, bopt ])
job = self.jobfile.job(options + gopt + bopt)
if not job:
continue
if proxy:
import db
proxy.dict['system'] = self.info[job.system]
val = self.info.get(job, self.stat)
if val is None:
print 'stat "%s" for job "%s" not found' % \
(self.stat, job)
if isinstance(val, (list, tuple)):
if len(val) == 1:
val = val[0]
@ -151,7 +160,7 @@ class StatOutput(object):
for j in xrange(len(baropts)):
val = data[i][j]
if val is None:
data[i][j] = [] * stacked
data[i][j] = [ 0.0 ] * stacked
elif len(val) != stacked:
raise ValueError, "some stats stacked, some not"
@ -159,29 +168,52 @@ class StatOutput(object):
if data.sum() == 0:
continue
bar_descs = [ opt.desc for opt in baropts ]
group_descs = [ opt.desc for opt in groupopts ]
if stacked:
try:
legend = self.info.rcategories
except:
legend = [ str(i) for i in xrange(stacked) ]
else:
legend = bar_descs
x = data.shape[0]
y = data.shape[1]
xkeep = [ i for i in xrange(x) if data[i].sum() != 0 ]
ykeep = [ i for i in xrange(y) if data[:,i].sum() != 0 ]
data = data.take(xkeep, axis=0)
data = data.take(ykeep, axis=1)
chart.data = data
chart = BarChart(data=data, xlabel='Benchmark', ylabel=self.label,
legend=legend, xticks=group_descs)
gopts = [ groupopts[i] for i in xkeep ]
bopts = [ baropts[i] for i in ykeep ]
bdescs = [ ' '.join([o.desc for o in opt]) for opt in bopts]
gdescs = [ ' '.join([o.desc for o in opt]) for opt in gopts]
if chart.legend is None:
if stacked:
try:
chart.legend = self.info.rcategories
except:
chart.legend = [ str(i) for i in xrange(stacked) ]
else:
chart.legend = bdescs
if chart.xticks is None:
chart.xticks = gdescs
chart.graph()
names = [ opt.name for opt in options ]
descs = [ opt.desc for opt in options ]
filename = '%s-%s.png' % (self.name, ':'.join(names))
if names[0] == 'run':
names = names[1:]
descs = descs[1:]
basename = '%s-%s' % (name, ':'.join(names))
desc = ' '.join(descs)
filepath = joinpath(directory, filename)
chart.savefig(filepath)
filename = re.sub(':', '%3A', filename)
print >>html, '''%s<br><img src="%s"><br>''' % (desc, filename)
pngname = '%s.png' % basename
psname = '%s.eps' % re.sub(':', '-', basename)
epsname = '%s.ps' % re.sub(':', '-', basename)
chart.savefig(joinpath(directory, pngname))
chart.savefig(joinpath(directory, epsname))
chart.savefig(joinpath(directory, psname))
html_name = urllib.quote(pngname)
print >>html, '''%s<br><img src="%s"><br>''' % (desc, html_name)
html.flush()
print >>html, '</body>'
print >>html, '</html>'

View file

@ -27,19 +27,39 @@
from orderdict import orderdict
import output
class FileData(dict):
def __init__(self, filename):
self.filename = filename
fd = file(filename)
current = []
for line in fd:
line = line.strip()
if line.startswith('>>>'):
current = []
self[line[3:]] = current
else:
current.append(line)
fd.close()
class RunData(dict):
def __init__(self, filename=None):
def __init__(self, filename):
self.filename = filename
def __getattr__(self, attr):
def __getattribute__(self, attr):
if attr == 'total':
total = 0.0
for value in self.itervalues():
total += value
return total
if attr == 'filedata':
return FileData(self.filename)
if attr == 'maxsymlen':
return max([ len(sym) for sym in self.iterkeys() ])
return super(RunData, self).__getattribute__(attr)
def display(self, output=None, limit=None, maxsymlen=None):
if not output:
import sys
@ -62,24 +82,12 @@ class RunData(dict):
for number,name in symbols:
print >>output, symbolf % (name, 100.0 * (float(number) / total))
class PCData(RunData):
def __init__(self, filename=None, categorize=None, showidle=True):
super(PCData, self).__init__(self, filename)
if filename is None:
return
fd = file(filename)
for line in fd:
if line.strip() == '>>>PC data':
break
for line in fd:
if line.startswith('>>>'):
break
filedata = self.filedata['PC data']
for line in filedata:
(symbol, count) = line.split()
if symbol == "0x0":
continue
@ -94,30 +102,21 @@ class PCData(RunData):
self[category] = count
fd.close()
class FuncNode(object):
def __new__(cls, filename = None):
if filename is None:
def __new__(cls, filedata=None):
if filedata is None:
return super(FuncNode, cls).__new__(cls)
fd = file(filename, 'r')
fditer = iter(fd)
nodes = {}
for line in fditer:
if line.strip() == '>>>function data':
break
for line in fditer:
if line.startswith('>>>'):
break
data = line.split()
node_id = int(data[0], 16)
for line in filedata['function data']:
data = line.split(' ')
node_id = long(data[0], 16)
node = FuncNode()
node.symbol = data[1]
node.count = int(data[2])
node.children = [ int(child, 16) for child in data[3:] ]
if node.symbol == '':
node.symbol = 'unknown'
node.count = long(data[2])
node.children = [ long(child, 16) for child in data[3:] ]
nodes[node_id] = node
for node in nodes.itervalues():
@ -128,13 +127,10 @@ class FuncNode(object):
child.parent = node
node.children = tuple(children)
if not nodes:
print filename
print filedata.filename
print nodes
return nodes[0]
def __init__(self, filename=None):
pass
def total(self):
total = self.count
for child in self.children:
@ -198,9 +194,14 @@ class FuncNode(object):
class FuncData(RunData):
def __init__(self, filename, categorize=None):
super(FuncData, self).__init__(filename)
self.tree = FuncNode(filename)
self.tree.aggregate(self, categorize, incategory=False)
self.total = self.tree.total()
tree = self.tree
tree.aggregate(self, categorize, incategory=False)
self.total = tree.total()
def __getattribute__(self, attr):
if attr == 'tree':
return FuncNode(self.filedata)
return super(FuncData, self).__getattribute__(attr)
def displayx(self, output=None, maxcount=None):
if output is None:
@ -274,6 +275,7 @@ class Profile(object):
try:
return self.data[run][cpu]
except KeyError:
print run, cpu
return None
def alldata(self):
@ -289,12 +291,16 @@ class Profile(object):
cpu = '%s.run%d' % (job.system, self.cpu)
data = self.getdata(run, cpu)
if not data:
return [ 0.0 for c in self.categories ]
return None
values = []
for category in self.categories:
values.append(data.get(category, 0.0))
return values
val = float(data.get(category, 0.0))
if val < 0.0:
raise ValueError, 'value is %f' % val
values.append(val)
total = sum(values)
return [ v / total * 100.0 for v in values ]
def dump(self):
for run,cpu,data in self.alldata():
@ -382,7 +388,6 @@ if __name__ == '__main__':
import getopt, re, sys
from os.path import expanduser
from output import StatOutput
from jobfile import JobFile
# default option values
numsyms = 10
@ -393,7 +398,7 @@ if __name__ == '__main__':
funcdata = True
jobfilename = 'Test.py'
dodot = False
dotformat = 'raw'
dotfile = None
textout = False
threshold = 0.01
inputfile = None
@ -409,7 +414,7 @@ if __name__ == '__main__':
elif o == '-c':
categorize = True
elif o == '-D':
dotformat = a
dotfile = a
elif o == '-d':
dodot = True
elif o == '-f':
@ -434,20 +439,24 @@ if __name__ == '__main__':
usage(1)
if inputfile:
data = FuncData(inputfile)
catfunc = None
if categorize:
catfunc = func_categorize
data = FuncData(inputfile, categorize=catfunc)
if dodot:
import pydot
dot = pydot.Dot()
data.dot(dot, threshold=threshold)
data.tree.dot(dot, threshold=threshold)
#dot.orientation = 'landscape'
#dot.ranksep='equally'
#dot.rank='samerank'
dot.write(dotfile, format=dotformat)
dot.write(dotfile, format='png')
else:
data.display(limit=numsyms)
else:
from jobfile import JobFile
jobfile = JobFile(jobfilename)
if funcdata:
@ -466,8 +475,11 @@ if __name__ == '__main__':
name = 'funcstacks%d' % cpu
else:
name = 'stacks%d' % cpu
output = StatOutput(name, jobfile, info=profile)
output.graph(graph)
output = StatOutput(jobfile, info=profile)
output.xlabel = 'System Configuration'
output.ylabel = '% CPU utilization'
output.stat = name
output.graph(name, graph)
if dodot:
for cpu in cpus:

View file

@ -259,14 +259,9 @@ def commands(options, command, args):
print 'only displaying sample %s' % options.ticks
source.ticks = [ int(x) for x in options.ticks.split() ]
import output
def display():
if options.graph:
output.graph(options.graphdir)
else:
output.display(options.binned, options.printmode)
from output import StatOutput
output = StatOutput(options.jobfile, source)
output.xlabel = 'System Configuration'
if command == 'stat' or command == 'formula':
if len(args) != 1:
@ -278,17 +273,18 @@ def commands(options, command, args):
stats = eval(args[0])
for stat in stats:
output = output.StatOutput(stat.name, options.jobfile, source)
output.stat = stat
output.label = stat.name
display()
output.ylabel = stat.name
if options.graph:
output.graph(stat.name, options.graphdir)
else:
output.display(stat.name, options.binned, options.printmode)
return
if len(args):
raise CommandException
system = source.__dict__[options.system]
from info import ProxyGroup
sim_seconds = source['sim_seconds']
proxy = ProxyGroup(system = source[options.system])
@ -300,7 +296,11 @@ def commands(options, command, args):
packets = etherdev.rxPackets + etherdev.txPackets
bps = etherdev.rxBandwidth + etherdev.txBandwidth
output = output.StatOutput(command, options.jobfile, source)
def display():
if options.graph:
output.graph(command, options.graphdir, proxy)
else:
output.display(command, options.binned, options.printmode)
if command == 'usertime':
import copy
@ -308,7 +308,7 @@ def commands(options, command, args):
user.bins = 'user'
output.stat = user / system.run0.numCycles
output.label = 'User Fraction'
output.ylabel = 'User Fraction'
display()
return
@ -338,13 +338,13 @@ def commands(options, command, args):
if command == 'pps':
output.stat = packets / sim_seconds
output.label = 'Packets/s'
output.ylabel = 'Packets/s'
display()
return
if command == 'bpt' or command == 'tpb':
output.stat = bytes / system.run0.numCycles * 8
output.label = 'bps / Hz'
output.ylabel = 'bps / Hz'
output.invert = command == 'tpb'
display()
return
@ -357,37 +357,38 @@ def commands(options, command, args):
if command == 'bps':
output.stat = bps / 1e9
output.label = 'Bandwidth (Gbps)'
output.ylabel = 'Bandwidth (Gbps)'
output.ylim = [ 0.0, 10.0 ]
display()
return
if command == 'bpp':
output.stat = bytes / packets
output.label = 'Bytes / Packet'
output.ylabel = 'Bytes / Packet'
display()
return
if command == 'rxbpp':
output.stat = etherdev.rxBytes / etherdev.rxPackets
output.label = 'Receive Bytes / Packet'
output.ylabel = 'Receive Bytes / Packet'
display()
return
if command == 'txbpp':
output.stat = etherdev.txBytes / etherdev.txPackets
output.label = 'Transmit Bytes / Packet'
output.ylabel = 'Transmit Bytes / Packet'
display()
return
if command == 'rtp':
output.stat = etherdev.rxPackets / etherdev.txPackets
output.label = 'rxPackets / txPackets'
output.ylabel = 'rxPackets / txPackets'
display()
return
if command == 'rtb':
output.stat = etherdev.rxBytes / etherdev.txBytes
output.label = 'rxBytes / txBytes'
output.ylabel = 'rxBytes / txBytes'
display()
return
@ -395,14 +396,14 @@ def commands(options, command, args):
if command == 'misses':
output.stat = misses
output.label = 'Overall MSHR Misses'
output.ylabel = 'Overall MSHR Misses'
display()
return
if command == 'mpkb':
output.stat = misses / (bytes / 1024)
output.binstats = [ misses ]
output.label = 'Misses / KB'
output.ylabel = 'Misses / KB'
display()
return
@ -410,7 +411,7 @@ def commands(options, command, args):
interrupts = system.run0.kern.faults[4]
output.stat = interrupts / kbytes
output.binstats = [ interrupts ]
output.label = 'Interrupts / KB'
output.ylabel = 'Interrupts / KB'
display()
return