summaryrefslogtreecommitdiff
path: root/btt/btt_plot.py
diff options
context:
space:
mode:
authorAlan D. Brunelle <alan.brunelle@hp.com>2009-10-08 14:12:12 -0400
committerAlan D. Brunelle <alan.brunelle@hp.com>2009-10-08 14:12:12 -0400
commit2e37a10ee8b470b805e7c26c703073dbc54ca84e (patch)
tree377cf2978262ff70087d60ae30905a2b56ba128b /btt/btt_plot.py
parenta155ab989ffc8b9cf95a631309e9a825d04bcc68 (diff)
downloadblktrace-2e37a10ee8b470b805e7c26c703073dbc54ca84e.tar.gz
blktrace-2e37a10ee8b470b805e7c26c703073dbc54ca84e.tar.bz2
btt: Added in I/O activity per device and system-wide
It now keeps track of I/O activity on a per-device basis (as well as a cumulative system-wide view). ``I/O activity'' is defined as defined as the time during which the device driver and device are activelty working on at least one I/O. Here's a sample output: ==================== I/O Active Period Information ==================== DEV | # Live Avg. Act Avg. !Act % Live ---------- | ---------- ------------- ------------- ------ (254, 0) | 0 0.000000000 0.000000000 0.00 ( 8, 17) | 0 0.000000000 0.000000000 0.00 ( 8, 16) | 29 0.909596815 0.094646263 90.87 ( 8, 33) | 0 0.000000000 0.000000000 0.00 ( 8, 32) | 168 0.097848226 0.068231948 59.06 ---------- | ---------- ------------- ------------- ------ Total Sys | 33 0.799808811 0.082334758 90.92 Also added a new btt -Z option that generates per-device and system-wide I/O activity data that can be plotted. Refer to the documentation updates (btt.1, btt.tex) for more information.
Diffstat (limited to 'btt/btt_plot.py')
-rwxr-xr-xbtt/btt_plot.py102
1 files changed, 87 insertions, 15 deletions
diff --git a/btt/btt_plot.py b/btt/btt_plot.py
index b795cec..b81dad5 100755
--- a/btt/btt_plot.py
+++ b/btt/btt_plot.py
@@ -73,7 +73,7 @@ title_str = None
type = None
verbose = False
-types = [ 'aqd', 'q2d', 'd2c', 'q2c', 'bnos' ]
+types = [ 'aqd', 'q2d', 'd2c', 'q2c', 'live', 'bnos' ]
progs = [ 'btt_plot_%s.py' % t for t in types ]
get_base = lambda file: file[file.find('_')+1:file.rfind('_')]
@@ -85,6 +85,14 @@ def fatal(msg):
print >>sys.stderr, 'FATAL: %s' % msg
sys.exit(1)
+#------------------------------------------------------------------------------
+def gen_legends(ax, legends):
+ leg = ax.legend(legends, 'best', shadow=True)
+ frame = leg.get_frame()
+ frame.set_facecolor('0.80')
+ for t in leg.get_texts():
+ t.set_fontsize('xx-small')
+
#----------------------------------------------------------------------
def get_data(files):
"""Retrieve data from files provided.
@@ -298,14 +306,6 @@ def generate_output(type, db):
return '%s%s' % (color, style)
#----------------------------------------------------------------------
- def gen_legends(a, legends):
- leg = ax.legend(legends, 'best', shadow=True)
- frame = leg.get_frame()
- frame.set_facecolor('0.80')
- for t in leg.get_texts():
- t.set_fontsize('xx-small')
-
- #----------------------------------------------------------------------
global add_legend, output_file, title_str, verbose
if output_file != None:
@@ -369,6 +369,79 @@ def get_files(type):
return files
#------------------------------------------------------------------------------
+def do_bnos(files):
+ for file in files:
+ base = get_base(file)
+ title_str = 'Block Numbers Accessed: %s' % base
+ output_file = 'bnos_%s.png' % base
+ generate_output(t, get_data([file]))
+
+#------------------------------------------------------------------------------
+def do_live(files):
+ global plot_size
+
+ #----------------------------------------------------------------------
+ def get_live_data(fn):
+ xs = []
+ ys = []
+ for line in open(fn, 'r'):
+ f = line.rstrip().split()
+ if f[0] != '#' and len(f) == 2:
+ xs.append(float(f[0]))
+ ys.append(float(f[1]))
+ return xs, ys
+
+ #----------------------------------------------------------------------
+ def live_sort(a, b):
+ if a[0] == 'sys' and b[0] == 'sys':
+ return 0
+ elif a[0] == 'sys' or a[2][0] < b[2][0]:
+ return -1
+ elif b[0] == 'sys' or a[2][0] > b[2][0]:
+ return 1
+ else:
+ return 0
+
+ #----------------------------------------------------------------------
+ def turn_off_ticks(ax):
+ for tick in ax.xaxis.get_major_ticks():
+ tick.tick1On = tick.tick2On = False
+ for tick in ax.yaxis.get_major_ticks():
+ tick.tick1On = tick.tick2On = False
+ for tick in ax.xaxis.get_minor_ticks():
+ tick.tick1On = tick.tick2On = False
+ for tick in ax.yaxis.get_minor_ticks():
+ tick.tick1On = tick.tick2On = False
+
+ #----------------------------------------------------------------------
+ fig = plt.figure(figsize=plot_size)
+ ax = fig.add_subplot(111)
+
+ db = []
+ for fn in files:
+ if not os.path.exists(fn):
+ continue
+ (xs, ys) = get_live_data(fn)
+ db.append([fn[:fn.find('_live.dat')], xs, ys])
+ db.sort(live_sort)
+
+ for rec in db:
+ ax.plot(rec[1], rec[2])
+
+ gen_title(fig, 'live', 'Active I/O Per Device')
+ ax.set_xlabel('Runtime (seconds)')
+ ax.set_ylabel('Device')
+ ax.grid(False)
+
+ ax.set_xlim(-0.1, db[0][1][-1]+1)
+ ax.set_yticks([idx for idx in range(0, len(db))])
+ ax.yaxis.set_ticklabels([rec[0] for rec in db])
+ turn_off_ticks(ax)
+
+ plt.savefig('live.png')
+ plt.savefig('live.eps')
+
+#------------------------------------------------------------------------------
if __name__ == '__main__':
files = parse_args(sys.argv)
@@ -378,15 +451,14 @@ if __name__ == '__main__':
files = get_files(t)
if len(files) == 0:
continue
- elif t != 'bnos':
+ elif t == 'bnos':
+ do_bnos(files)
+ elif t == 'live':
+ do_live(files)
+ else:
generate_output(t, get_data(files))
continue
- for file in files:
- base = get_base(file)
- title_str = 'Block Numbers Accessed: %s' % base
- output_file = 'bnos_%s.png' % base
- generate_output(t, get_data([file]))
elif len(files) < 1:
fatal('Need data files to process')
else: