diff options
| author | Björn B. Brandenburg <bbb@cs.unc.edu> | 2010-03-28 00:20:56 -0400 |
|---|---|---|
| committer | Björn B. Brandenburg <bbb@cs.unc.edu> | 2010-03-28 00:20:56 -0400 |
| commit | 98ce8d88ca3d8476759c006a9ba8262beb045c5e (patch) | |
| tree | 818a9a85ac1ff8f6c9e853c4d9e76743aeaba95b | |
| parent | 92e88bb922d5391e30cd5c506da9ebf74b1c0249 (diff) | |
improve pm2 plotter:
- error bars
- hot vs. hot error
- keep aggregate CSVs around.
| -rwxr-xr-x | plot_pm2.py | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/plot_pm2.py b/plot_pm2.py index 09b2d49..40e6a63 100755 --- a/plot_pm2.py +++ b/plot_pm2.py | |||
| @@ -13,7 +13,7 @@ import stats | |||
| 13 | import defapp | 13 | import defapp |
| 14 | 14 | ||
| 15 | from plot import decode | 15 | from plot import decode |
| 16 | from gnuplot import gnuplot, FORMATS | 16 | from gnuplot import gnuplot, FileGraph, FORMATS |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| @@ -75,6 +75,8 @@ PMO_AGGR_SUBPLOTS = [ | |||
| 75 | # (0, 10, 7, True), | 75 | # (0, 10, 7, True), |
| 76 | # (0, 10, 8, True), | 76 | # (0, 10, 8, True), |
| 77 | (0, 10, 9, True), | 77 | (0, 10, 9, True), |
| 78 | (0, 8, 7, False), # difference of second to first hot access | ||
| 79 | (0, 9, 8, False), # difference of third to second hot access | ||
| 78 | ] | 80 | ] |
| 79 | 81 | ||
| 80 | PMO_AGGR_COMBINE = [ | 82 | PMO_AGGR_COMBINE = [ |
| @@ -104,6 +106,7 @@ options = [ | |||
| 104 | o(None, '--wide', action='store_true', dest='wide'), | 106 | o(None, '--wide', action='store_true', dest='wide'), |
| 105 | o(None, '--split', action='store_true', dest='split'), | 107 | o(None, '--split', action='store_true', dest='split'), |
| 106 | o(None, '--log-y', action='store_true', dest='logy'), | 108 | o(None, '--log-y', action='store_true', dest='logy'), |
| 109 | o(None, '--errorbar', action='store_true', dest='errbar'), | ||
| 107 | o(None, '--extend', action='store', type='float', dest='extend'), | 110 | o(None, '--extend', action='store', type='float', dest='extend'), |
| 108 | o(None, '--aggregate', action='store_true', dest='aggregate'), | 111 | o(None, '--aggregate', action='store_true', dest='aggregate'), |
| 109 | o('-c', '--cycles-per-usec', action='store', type='float', dest='cycles_per_usec'), | 112 | o('-c', '--cycles-per-usec', action='store', type='float', dest='cycles_per_usec'), |
| @@ -117,7 +120,8 @@ defaults = { | |||
| 117 | 'aggregate' : False, | 120 | 'aggregate' : False, |
| 118 | 'extend' : 1.5, | 121 | 'extend' : 1.5, |
| 119 | 'cycles_per_usec' : None, | 122 | 'cycles_per_usec' : None, |
| 120 | 'logy' : False, | 123 | 'logy' : False, |
| 124 | 'errbar' : False, | ||
| 121 | } | 125 | } |
| 122 | 126 | ||
| 123 | def extract_cols(data, xcol, ycol1, ycol2, cast=int, cpu_filter=lambda x, y: True): | 127 | def extract_cols(data, xcol, ycol1, ycol2, cast=int, cpu_filter=lambda x, y: True): |
| @@ -346,11 +350,16 @@ class CyclePlotter(defapp.App): | |||
| 346 | mems = [tag for (tag, _) in MACHINE_TOPOLOGY[host][1]] | 350 | mems = [tag for (tag, _) in MACHINE_TOPOLOGY[host][1]] |
| 347 | columns = [] | 351 | columns = [] |
| 348 | idx = 2 | 352 | idx = 2 |
| 353 | header = ["wss"] | ||
| 349 | for (x, y, yminus, split) in PMO_AGGR_SUBPLOTS: | 354 | for (x, y, yminus, split) in PMO_AGGR_SUBPLOTS: |
| 350 | tags = ['all'] | 355 | tags = ['all'] |
| 351 | if split: | 356 | if split: |
| 352 | tags += mems | 357 | tags += mems |
| 353 | for tag in tags: | 358 | for tag in tags: |
| 359 | col_name = "%s %s" % (PMO_COL_LABEL[y][1], tag) | ||
| 360 | if not yminus is None: | ||
| 361 | col_name += ' - ' + PMO_COL_LABEL[yminus][1] | ||
| 362 | header += [col_name + " avg", col_name + " std", col_name + " wc"] | ||
| 354 | columns.append((x, y, yminus, tag, idx)) | 363 | columns.append((x, y, yminus, tag, idx)) |
| 355 | idx += 3 | 364 | idx += 3 |
| 356 | 365 | ||
| @@ -360,7 +369,10 @@ class CyclePlotter(defapp.App): | |||
| 360 | data[:, 1:] /= self.options.cycles_per_usec | 369 | data[:, 1:] /= self.options.cycles_per_usec |
| 361 | else: | 370 | else: |
| 362 | yunit = "(cycles)" | 371 | yunit = "(cycles)" |
| 363 | tmp = write_csv_file(None, data) | 372 | |
| 373 | csvfile = "xxx-%s" % datafile | ||
| 374 | |||
| 375 | write_csv_file(csvfile, data, header, width=max([len(h) for h in header])) | ||
| 364 | 376 | ||
| 365 | rw = int(conf['wcycle']) | 377 | rw = int(conf['wcycle']) |
| 366 | rw = 1.0 / rw * 100 if rw != 0 else 0 | 378 | rw = 1.0 / rw * 100 if rw != 0 else 0 |
| @@ -378,9 +390,10 @@ class CyclePlotter(defapp.App): | |||
| 378 | label = PMO_COL_LABEL[y][0] | 390 | label = PMO_COL_LABEL[y][0] |
| 379 | if y == 10: | 391 | if y == 10: |
| 380 | label += " from %s" % PMO_MEM[tag] | 392 | label += " from %s" % PMO_MEM[tag] |
| 381 | graphs += [ | 393 | graphs.append( |
| 382 | (tmp.name, 1, idx + offset, label), | 394 | FileGraph( |
| 383 | ] | 395 | csvfile, xcol=1, ycol=idx + offset, title=label, |
| 396 | error=idx + offset + 1 if kind == 'avg' and self.options.errbar else None)) | ||
| 384 | xlabel = "working set size (kilobytes)" | 397 | xlabel = "working set size (kilobytes)" |
| 385 | ylabel = "time to complete access " + yunit | 398 | ylabel = "time to complete access " + yunit |
| 386 | title = "measured %s WSS access time (%.2f%% writes)" % (long, rw) | 399 | title = "measured %s WSS access time (%.2f%% writes)" % (long, rw) |
| @@ -397,9 +410,10 @@ class CyclePlotter(defapp.App): | |||
| 397 | for (x, y, yminus, tag, idx) in columns: | 410 | for (x, y, yminus, tag, idx) in columns: |
| 398 | if not (yminus is None) and tag != 'all': | 411 | if not (yminus is None) and tag != 'all': |
| 399 | label = "%s" % PMO_MEM[tag] | 412 | label = "%s" % PMO_MEM[tag] |
| 400 | graphs += [ | 413 | graphs.append( |
| 401 | (tmp.name, 1, idx + offset, label), | 414 | FileGraph( |
| 402 | ] | 415 | csvfile, xcol=1, ycol=idx + offset, title=label, |
| 416 | error=idx + offset + 1 if kind == 'avg' and self.options.errbar else None)) | ||
| 403 | xlabel = "working set size (kilobytes)" | 417 | xlabel = "working set size (kilobytes)" |
| 404 | ylabel = "per-sample delta to hot access " + yunit | 418 | ylabel = "per-sample delta to hot access " + yunit |
| 405 | title = "measured %s overhead (%.2f%% writes)" % (long, rw) | 419 | title = "measured %s overhead (%.2f%% writes)" % (long, rw) |
| @@ -408,7 +422,25 @@ class CyclePlotter(defapp.App): | |||
| 408 | fname = "%s_delta_%s" % (name, kind) | 422 | fname = "%s_delta_%s" % (name, kind) |
| 409 | gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=fname, | 423 | gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=fname, |
| 410 | yrange=yrange, logscale=axis, format=self.options.format) | 424 | yrange=yrange, logscale=axis, format=self.options.format) |
| 411 | del tmp | 425 | |
| 426 | graphs = [] | ||
| 427 | for (x, y, yminus, tag, idx) in columns: | ||
| 428 | if y in [8, 9] and yminus in [7, 8] and tag == 'all': | ||
| 429 | label = "%s to %s" % (PMO_COL_LABEL[yminus][0], PMO_COL_LABEL[y][0]) | ||
| 430 | graphs.append( | ||
| 431 | FileGraph( | ||
| 432 | csvfile, xcol=1, ycol=idx + offset, title=label, | ||
| 433 | error=idx + offset + 1 if kind == 'avg' and self.options.errbar else None)) | ||
| 434 | xlabel = "working set size (kilobytes)" | ||
| 435 | ylabel = "per-sample delta to previous hot access " + yunit | ||
| 436 | title = "measured %s differences (%.2f%% writes)" % (long, rw) | ||
| 437 | yrange = None | ||
| 438 | |||
| 439 | fname = "%s_delta-h_%s" % (name, kind) | ||
| 440 | gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=fname, | ||
| 441 | yrange=yrange, logscale=axis, format=self.options.format) | ||
| 442 | |||
| 443 | # del tmp | ||
| 412 | 444 | ||
| 413 | # stats delta | 445 | # stats delta |
| 414 | # find hot column | 446 | # find hot column |
| @@ -433,9 +465,7 @@ class CyclePlotter(defapp.App): | |||
| 433 | if yminus is None and tag != 'all': | 465 | if yminus is None and tag != 'all': |
| 434 | label = PMO_COL_LABEL[y][0] | 466 | label = PMO_COL_LABEL[y][0] |
| 435 | label = PMO_MEM[tag] | 467 | label = PMO_MEM[tag] |
| 436 | graphs += [ | 468 | graphs.append(FileGraph(tmp.name, xcol=1, ycol=idx+offset, title=label)) |
| 437 | (tmp.name, 1, idx + offset, label), | ||
| 438 | ] | ||
| 439 | xlabel = "working set size (kilobytes)" | 469 | xlabel = "working set size (kilobytes)" |
| 440 | ylabel = "delta to third hot access " + yunit | 470 | ylabel = "delta to third hot access " + yunit |
| 441 | title = "difference of %s access costs (%.2f%% writes)" % (long, rw) | 471 | title = "difference of %s access costs (%.2f%% writes)" % (long, rw) |
| @@ -444,7 +474,7 @@ class CyclePlotter(defapp.App): | |||
| 444 | fname = "%s_diff_%s" % (name, kind) | 474 | fname = "%s_diff_%s" % (name, kind) |
| 445 | gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=fname, | 475 | gnuplot(graphs, xlabel=xlabel, ylabel=ylabel, title=title, fname=fname, |
| 446 | yrange=yrange, logscale=axis, format=self.options.format) | 476 | yrange=yrange, logscale=axis, format=self.options.format) |
| 447 | del tmp | 477 | # del tmp |
| 448 | 478 | ||
| 449 | def plot_file(self, datafile): | 479 | def plot_file(self, datafile): |
| 450 | bname = basename(datafile) | 480 | bname = basename(datafile) |
