diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-07-03 16:45:57 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-07-03 16:45:57 -0400 |
commit | 1d4c0da88cdd6fada48350e1b9e64602b8ca863b (patch) | |
tree | 3b1ea8f03403c595ecab7eff91d976c70fd69ecc | |
parent | 07077acb1472b871a508d1b4c4f74e4e8eb6f1ae (diff) |
support comparison overhead plotting
-rwxr-xr-x | gnuplot.py | 5 | ||||
-rwxr-xr-x | oplot.py | 111 |
2 files changed, 108 insertions, 8 deletions
@@ -63,7 +63,10 @@ class FileGraph(object): | |||
63 | using_txt = "%s:%s" % (self.xcol, self.ycol) | 63 | using_txt = "%s:%s" % (self.xcol, self.ycol) |
64 | style = self.style if self.style else default_style | 64 | style = self.style if self.style else default_style |
65 | style_txt = " with %s" % style if style else "" | 65 | style_txt = " with %s" % style if style else "" |
66 | title_txt = ' title "%s"' % self.title if self.title else "" | 66 | if self.title == 'notitle': |
67 | title_txt = ' notitle' | ||
68 | else: | ||
69 | title_txt = ' title "%s"' % self.title if self.title else "" | ||
67 | smooth_txt = ' smooth %s' % self.smooth if self.smooth else "" | 70 | smooth_txt = ' smooth %s' % self.smooth if self.smooth else "" |
68 | return "'%s' using %s%s%s%s" % \ | 71 | return "'%s' using %s%s%s%s" % \ |
69 | (self.fname, using_txt, title_txt, style_txt, smooth_txt) | 72 | (self.fname, using_txt, title_txt, style_txt, smooth_txt) |
@@ -2,6 +2,7 @@ | |||
2 | import defapp | 2 | import defapp |
3 | 3 | ||
4 | from plot import decode | 4 | from plot import decode |
5 | from dplot import sched_name | ||
5 | from util import load_csv_file, load_binary_file, write_csv_file | 6 | from util import load_csv_file, load_binary_file, write_csv_file |
6 | from stats import iqr_cutoff | 7 | from stats import iqr_cutoff |
7 | 8 | ||
@@ -59,6 +60,8 @@ options = [ | |||
59 | o(None, '--cycles', action='store', dest='cycles', type='int', | 60 | o(None, '--cycles', action='store', dest='cycles', type='int', |
60 | help='how many cycles per usec'), | 61 | help='how many cycles per usec'), |
61 | 62 | ||
63 | o(None, '--compare', action='store', dest='compare', | ||
64 | help='plot overhead comparison', choices=['max', 'avg']), | ||
62 | ] | 65 | ] |
63 | 66 | ||
64 | defaults = { | 67 | defaults = { |
@@ -86,12 +89,14 @@ defaults = { | |||
86 | 'xmax' : None, | 89 | 'xmax' : None, |
87 | 'ymax' : None, | 90 | 'ymax' : None, |
88 | 'ylog' : False, | 91 | 'ylog' : False, |
92 | |||
93 | 'compare' : None, | ||
89 | } | 94 | } |
90 | 95 | ||
91 | 96 | ||
92 | TXT = { | 97 | TXT = { |
93 | 'RELEASE-LATENCY' : 'timer interrupt latency', | 98 | 'RELEASE-LATENCY' : 'event latency', |
94 | 'RELEASE' : 'job release overhead', | 99 | 'RELEASE' : 'release interrupt overhead', |
95 | 'SCHED' : 'scheduling overhead', | 100 | 'SCHED' : 'scheduling overhead', |
96 | 'SCHED2' : 'post-scheduling overhead', | 101 | 'SCHED2' : 'post-scheduling overhead', |
97 | 'CXS' : 'context-switch overhead', | 102 | 'CXS' : 'context-switch overhead', |
@@ -291,7 +296,7 @@ class OverheadPlotter(defapp.App): | |||
291 | 296 | ||
292 | self.render(p) | 297 | self.render(p) |
293 | 298 | ||
294 | def prepare_trends(self, datafile, name, conf): | 299 | def prepare_trends(self, datafile, name, conf, want_avg_ymax=False): |
295 | data = load_csv_file(datafile) | 300 | data = load_csv_file(datafile) |
296 | if not self.options.per_proc and \ | 301 | if not self.options.per_proc and \ |
297 | 'host' in conf and conf['host'] in HOST_CPUS: | 302 | 'host' in conf and conf['host'] in HOST_CPUS: |
@@ -312,7 +317,10 @@ class OverheadPlotter(defapp.App): | |||
312 | r[std_idx]] | 317 | r[std_idx]] |
313 | for r in data] | 318 | for r in data] |
314 | 319 | ||
315 | max_y = numpy.amax(data[:,wc_idx]) | 320 | if want_avg_ymax: |
321 | max_y = numpy.amax(data[:,avg_idx]) | ||
322 | else: | ||
323 | max_y = numpy.amax(data[:,wc_idx]) | ||
316 | 324 | ||
317 | return (self.write(rows, name), cpus, max_y) | 325 | return (self.write(rows, name), cpus, max_y) |
318 | 326 | ||
@@ -363,6 +371,92 @@ class OverheadPlotter(defapp.App): | |||
363 | 371 | ||
364 | self.render(p) | 372 | self.render(p) |
365 | 373 | ||
374 | def plot_comparison(self, datafiles): | ||
375 | |||
376 | if self.options.compare == 'max': | ||
377 | stat = 'maximum' | ||
378 | want_avg_ymax = False | ||
379 | else: | ||
380 | stat = 'average' | ||
381 | want_avg_ymax = True | ||
382 | |||
383 | plots = [] | ||
384 | max_y = 0 | ||
385 | cpus = 0 | ||
386 | overheads = set() | ||
387 | |||
388 | for i, datafile in enumerate(datafiles): | ||
389 | self.out("[%d/%d] Processing %s ..." % (i + 1, len(datafiles), datafile)) | ||
390 | bname = basename(datafile) | ||
391 | name, ext = splitext(bname) | ||
392 | conf = decode(name) | ||
393 | overheads.add(conf['overhead']) | ||
394 | fname, _cpus, _max_y = self.prepare_trends(datafile, name, conf, want_avg_ymax) | ||
395 | max_y = max(max_y, _max_y) | ||
396 | cpus = max(cpus, _cpus) | ||
397 | plots.append((fname, conf)) | ||
398 | |||
399 | assert len(overheads) == 1 | ||
400 | overhead = overheads.pop() | ||
401 | |||
402 | |||
403 | schedulers = '_'.join([conf['scheduler'] for (_, conf) in plots]) | ||
404 | |||
405 | name = 'compare_%s-%s_%s' % (stat, overhead, schedulers) | ||
406 | |||
407 | p = self.make_plot(name) | ||
408 | |||
409 | p.title = "%s measured %s" \ | ||
410 | % (stat, TXT[overhead]) | ||
411 | |||
412 | p.ylabel = "overhead in microseconds" | ||
413 | if self.options.per_proc: | ||
414 | p.xlabel = "number of tasks per processor" | ||
415 | else: | ||
416 | p.xlabel = "number of tasks" | ||
417 | |||
418 | p.xticks = (0, max(cpus, 10)) | ||
419 | if self.options.xmax: | ||
420 | p.xrange = (0, self.options.xmax) | ||
421 | elif self.options.per_proc: | ||
422 | p.xrange = (0.5, 20.5) | ||
423 | p.xticks = (0, 1) | ||
424 | else: | ||
425 | p.xrange = (0, ceil(cpus * 20 / 100.0) * 100) | ||
426 | |||
427 | if self.options.ymax: | ||
428 | p.yrange = (0, self.options.ymax) | ||
429 | else: | ||
430 | p.yrange = (0, (ceil(max_y / 10.0)) * 10) | ||
431 | |||
432 | for (fname, conf) in plots: | ||
433 | name = sched_name(conf['scheduler']) | ||
434 | if self.options.compare == 'max': | ||
435 | p.curves += [ | ||
436 | curve(fname, xcol=1, ycol=2, title=name)] | ||
437 | else: | ||
438 | p.curves += [ | ||
439 | curve(fname, xcol=1, ycol=3, title=name)] | ||
440 | # curve(fname, xcol=1, ycol=3, error=4, title='notitle')] | ||
441 | |||
442 | #### Styling. | ||
443 | |||
444 | marker = 'lines' | ||
445 | if len(p.curves) > 2: | ||
446 | p.curves[2].style = marker + " ls 4" | ||
447 | |||
448 | if len(p.curves) > 3: | ||
449 | p.curves[3].style = marker + " ls 6" | ||
450 | |||
451 | p.font_size = '7' | ||
452 | p.size = ('6in', '2.50in') | ||
453 | p.monochrome = True #False | ||
454 | p.dashed_lines = True #True | ||
455 | p.key = 'top left' | ||
456 | p.default_style = marker + ' lw 1' | ||
457 | p.pointsize = 2 | ||
458 | |||
459 | self.render(p) | ||
366 | 460 | ||
367 | def plot_file(self, datafile): | 461 | def plot_file(self, datafile): |
368 | bname = basename(datafile) | 462 | bname = basename(datafile) |
@@ -390,9 +484,12 @@ class OverheadPlotter(defapp.App): | |||
390 | if self.options.outlier_file: | 484 | if self.options.outlier_file: |
391 | self.options.outliers = load_outliers(self.options.outlier_file) | 485 | self.options.outliers = load_outliers(self.options.outlier_file) |
392 | 486 | ||
393 | for i, datafile in enumerate(self.args): | 487 | if not self.options.compare is None: |
394 | self.out("[%d/%d] Processing %s ..." % (i + 1, len(self.args), datafile)) | 488 | self.plot_comparison(self.args) |
395 | self.plot_file(datafile) | 489 | else: |
490 | for i, datafile in enumerate(self.args): | ||
491 | self.out("[%d/%d] Processing %s ..." % (i + 1, len(self.args), datafile)) | ||
492 | self.plot_file(datafile) | ||
396 | 493 | ||
397 | if __name__ == "__main__": | 494 | if __name__ == "__main__": |
398 | OverheadPlotter().launch() | 495 | OverheadPlotter().launch() |