diff options
| author | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2011-01-27 00:51:17 -0500 |
|---|---|---|
| committer | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2011-01-27 00:51:17 -0500 |
| commit | c4edd95d28b9212e09e8caca0d6b11937f453995 (patch) | |
| tree | 7237b64d71c9e9856e13a687eab336691a1a26f6 | |
| parent | 27f0b6ca2baac29c1b61001306caf4186f5c108a (diff) | |
Added support for visualizing arbitrary actions.wip-events
| -rw-r--r-- | unit_trace/sanitizer.py | 10 | ||||
| -rw-r--r-- | unit_trace/trace_reader.py | 14 | ||||
| -rw-r--r-- | unit_trace/viz/canvas.py | 63 | ||||
| -rw-r--r-- | unit_trace/viz/convert.py | 31 | ||||
| -rw-r--r-- | unit_trace/viz/graph.py | 72 | ||||
| -rw-r--r-- | unit_trace/viz/schedule.py | 125 |
6 files changed, 263 insertions, 52 deletions
diff --git a/unit_trace/sanitizer.py b/unit_trace/sanitizer.py index 598379a..fc66170 100644 --- a/unit_trace/sanitizer.py +++ b/unit_trace/sanitizer.py | |||
| @@ -14,6 +14,8 @@ def sanitizer(stream): | |||
| 14 | job_2s_released = [] # list of tasks which have released their job 2s | 14 | job_2s_released = [] # list of tasks which have released their job 2s |
| 15 | jobs_switched_to = [] | 15 | jobs_switched_to = [] |
| 16 | 16 | ||
| 17 | released = False | ||
| 18 | |||
| 17 | for record in stream: | 19 | for record in stream: |
| 18 | 20 | ||
| 19 | # Ignore records which are not events (e.g. the num_cpus record) | 21 | # Ignore records which are not events (e.g. the num_cpus record) |
| @@ -21,6 +23,13 @@ def sanitizer(stream): | |||
| 21 | yield record | 23 | yield record |
| 22 | continue | 24 | continue |
| 23 | 25 | ||
| 26 | if record.type_name == 'release': | ||
| 27 | released = released or True | ||
| 28 | |||
| 29 | if record.type_name == 'action' and released: | ||
| 30 | yield record | ||
| 31 | continue | ||
| 32 | |||
| 24 | # All records with job < 2 are garbage | 33 | # All records with job < 2 are garbage |
| 25 | if record.job < 2: | 34 | if record.job < 2: |
| 26 | continue | 35 | continue |
| @@ -50,4 +59,5 @@ def sanitizer(stream): | |||
| 50 | if (record.pid,record.job) not in jobs_switched_to: | 59 | if (record.pid,record.job) not in jobs_switched_to: |
| 51 | record.job -= 1 | 60 | record.job -= 1 |
| 52 | 61 | ||
| 62 | |||
| 53 | yield record | 63 | yield record |
diff --git a/unit_trace/trace_reader.py b/unit_trace/trace_reader.py index a4c3c05..fe5c03c 100644 --- a/unit_trace/trace_reader.py +++ b/unit_trace/trace_reader.py | |||
| @@ -93,7 +93,6 @@ def trace_reader(files): | |||
| 93 | 93 | ||
| 94 | # Keep pulling records as long as we have a buffer | 94 | # Keep pulling records as long as we have a buffer |
| 95 | while len(file_iter_buff) > 0: | 95 | while len(file_iter_buff) > 0: |
| 96 | |||
| 97 | # Select the earliest record from those at the heads of the buffers | 96 | # Select the earliest record from those at the heads of the buffers |
| 98 | earliest = -1 | 97 | earliest = -1 |
| 99 | buff_to_refill = -1 | 98 | buff_to_refill = -1 |
| @@ -120,7 +119,8 @@ def trace_reader(files): | |||
| 120 | del file_iters[buff_to_refill] | 119 | del file_iters[buff_to_refill] |
| 121 | 120 | ||
| 122 | # Check for monotonically increasing time | 121 | # Check for monotonically increasing time |
| 123 | if last_time is not None and earliest.when < last_time: | 122 | if last_time is not None and earliest.when != 0 and earliest.when < last_time: |
| 123 | print("FATAL Old: %s, New: %s" % (last_time, earliest.when)) | ||
| 124 | exit("FATAL ERROR: trace_reader.py: out-of-order record produced") | 124 | exit("FATAL ERROR: trace_reader.py: out-of-order record produced") |
| 125 | else: | 125 | else: |
| 126 | last_time = earliest.when | 126 | last_time = earliest.when |
| @@ -203,6 +203,12 @@ class StHeader: | |||
| 203 | keys = ['type','cpu','pid','job'] | 203 | keys = ['type','cpu','pid','job'] |
| 204 | message = 'The header.' | 204 | message = 'The header.' |
| 205 | 205 | ||
| 206 | class StActionData: | ||
| 207 | format = 'Qb' | ||
| 208 | formatStr = struct.Struct(StHeader.format + format) | ||
| 209 | keys = StHeader.keys + ['when','action'] | ||
| 210 | message = 'An action was performed.' | ||
| 211 | |||
| 206 | class StNameData: | 212 | class StNameData: |
| 207 | format = '16s' | 213 | format = '16s' |
| 208 | formatStr = struct.Struct(StHeader.format + format) | 214 | formatStr = struct.Struct(StHeader.format + format) |
| @@ -269,7 +275,7 @@ class StSysReleaseData: | |||
| 269 | def _get_type(type_num): | 275 | def _get_type(type_num): |
| 270 | types = [None,StNameData,StParamData,StReleaseData,StAssignedData, | 276 | types = [None,StNameData,StParamData,StReleaseData,StAssignedData, |
| 271 | StSwitchToData,StSwitchAwayData,StCompletionData,StBlockData, | 277 | StSwitchToData,StSwitchAwayData,StCompletionData,StBlockData, |
| 272 | StResumeData,StSysReleaseData] | 278 | StResumeData,StActionData,StSysReleaseData] |
| 273 | if type_num > len(types)-1 or type_num < 1: | 279 | if type_num > len(types)-1 or type_num < 1: |
| 274 | raise Exception | 280 | raise Exception |
| 275 | return types[type_num] | 281 | return types[type_num] |
| @@ -278,5 +284,5 @@ def _get_type(type_num): | |||
| 278 | # programmers of other modules) | 284 | # programmers of other modules) |
| 279 | def _get_type_name(type_num): | 285 | def _get_type_name(type_num): |
| 280 | type_names = [None,"name","params","release","assign","switch_to", | 286 | type_names = [None,"name","params","release","assign","switch_to", |
| 281 | "switch_away","completion","block","resume","sys_release"] | 287 | "switch_away","completion","block","resume","action","sys_release"] |
| 282 | return type_names[type_num] | 288 | return type_names[type_num] |
diff --git a/unit_trace/viz/canvas.py b/unit_trace/viz/canvas.py index badebe9..2c977ae 100644 --- a/unit_trace/viz/canvas.py +++ b/unit_trace/viz/canvas.py | |||
| @@ -521,14 +521,44 @@ class Canvas(object): | |||
| 521 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, | 521 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, |
| 522 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) | 522 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) |
| 523 | 523 | ||
| 524 | def draw_action_symbol(self, item, action, x, y, height, selected): | ||
| 525 | """Draws a release arrow: x, y should give the top (northernmost | ||
| 526 | point) of the arrow. The height includes the arrowhead.""" | ||
| 527 | |||
| 528 | color = {False : GraphFormat.BORDER_COLOR, | ||
| 529 | True : GraphFormat.HIGHLIGHT_COLOR}[selected] | ||
| 530 | |||
| 531 | colors = [self.get_bar_pattern(item).get_color_list()[0], color] | ||
| 532 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | ||
| 533 | |||
| 534 | for i in range(0, 2): | ||
| 535 | color = colors[i] | ||
| 536 | draw_func = draw_funcs[i] | ||
| 537 | |||
| 538 | draw_func(self, [(x, y), (x - height / Canvas.SQRT3, \ | ||
| 539 | y - height), \ | ||
| 540 | (x + height / Canvas.SQRT3, \ | ||
| 541 | y - height), \ | ||
| 542 | (x, y)], color, GraphFormat.BORDER_THICKNESS) | ||
| 543 | |||
| 544 | self.draw_label(str(action), x, y - height / 2 - .1 * height, | ||
| 545 | GraphFormat.DEF_FOPTS_LABEL, | ||
| 546 | AlignMode.CENTER, AlignMode.CENTER, True) | ||
| 547 | |||
| 548 | def add_sel_action_symbol(self, x, y, height, event): | ||
| 549 | self.add_sel_region(SelectableRegion(x - height / Canvas.SQRT3, | ||
| 550 | y - height, 2.0 * height / Canvas.SQRT3, height, event)) | ||
| 551 | |||
| 524 | def draw_release_arrow_small(self, x, y, height, selected): | 552 | def draw_release_arrow_small(self, x, y, height, selected): |
| 525 | """Draws a small release arrow (most likely coming off the x-axis, although | 553 | """Draws a small release arrow (most likely coming off the x-axis, although |
| 526 | this method doesn't enforce this): x, y should give the top of the arrow""" | 554 | this method doesn't enforce this): x, y should give the top of the arrow""" |
| 527 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 555 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
| 528 | 556 | ||
| 529 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 557 | color = {False : GraphFormat.BORDER_COLOR, |
| 558 | True : GraphFormat.HIGHLIGHT_COLOR}[selected] | ||
| 530 | 559 | ||
| 531 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ | 560 | self.draw_line((x, y), |
| 561 | (x - small_arrowhead_height, y + small_arrowhead_height), | ||
| 532 | color, GraphFormat.BORDER_THICKNESS) | 562 | color, GraphFormat.BORDER_THICKNESS) |
| 533 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ | 563 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ |
| 534 | color, GraphFormat.BORDER_THICKNESS) | 564 | color, GraphFormat.BORDER_THICKNESS) |
| @@ -754,13 +784,35 @@ class CairoCanvas(Canvas): | |||
| 754 | self.surface.ctx.set_line_width(thickness * self.scale) | 784 | self.surface.ctx.set_line_width(thickness * self.scale) |
| 755 | self.surface.ctx.stroke() | 785 | self.surface.ctx.stroke() |
| 756 | 786 | ||
| 787 | def draw_circle(self, x, y, radius, fill_color, border_color, | ||
| 788 | thickness, do_snap=True): | ||
| 789 | p = self.surface.get_real_coor(x, y) | ||
| 790 | if do_snap: | ||
| 791 | p = (snap(p[0]), snap(p[1])) | ||
| 792 | |||
| 793 | self.surface.ctx.save() | ||
| 794 | self.surface.ctx.arc(p[0], p[1], radius, 0.0, 2 * math.pi) | ||
| 795 | self.surface.ctx.set_source_rgb(border_color[0], | ||
| 796 | border_color[1], | ||
| 797 | border_color[2]) | ||
| 798 | self.surface.ctx.set_line_width(thickness * self.scale) | ||
| 799 | self.surface.ctx.stroke() | ||
| 800 | self.surface.ctx.arc(p[0], p[1], radius, 0.0, 2 * math.pi) | ||
| 801 | self.surface.ctx.set_source_rgb(fill_color[0], | ||
| 802 | fill_color[1], | ||
| 803 | fill_color[2]) | ||
| 804 | self.surface.ctx.fill() | ||
| 805 | self.surface.ctx.restore() | ||
| 806 | |||
| 757 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): | 807 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): |
| 758 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in coor_list] | 808 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) \ |
| 809 | for coor in coor_list] | ||
| 759 | 810 | ||
| 760 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) | 811 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) |
| 761 | if do_snap: | 812 | if do_snap: |
| 762 | for i in range(0, len(real_coor_list)): | 813 | for i in range(0, len(real_coor_list)): |
| 763 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) | 814 | real_coor_list[i] = (snap(real_coor_list[i][0]), |
| 815 | snap(real_coor_list[i][1])) | ||
| 764 | 816 | ||
| 765 | for coor in real_coor_list[1:]: | 817 | for coor in real_coor_list[1:]: |
| 766 | self.surface.ctx.line_to(coor[0], coor[1]) | 818 | self.surface.ctx.line_to(coor[0], coor[1]) |
| @@ -830,7 +882,8 @@ class CairoCanvas(Canvas): | |||
| 830 | f_descent_factor, width_factor, f_height_factor, | 882 | f_descent_factor, width_factor, f_height_factor, |
| 831 | do_snap) | 883 | do_snap) |
| 832 | 884 | ||
| 833 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 885 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, |
| 886 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | ||
| 834 | """Draws a label with the given parameters, with the given horizontal and vertical justification.""" | 887 | """Draws a label with the given parameters, with the given horizontal and vertical justification.""" |
| 835 | 888 | ||
