summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/schedule.py
diff options
context:
space:
mode:
authorGary Bressler <garybressler@nc.rr.com>2010-03-20 12:47:31 -0400
committerGary Bressler <garybressler@nc.rr.com>2010-03-20 12:47:31 -0400
commitc712c699126e16003ee69e2d82e51007ab2f58ea (patch)
tree724913e93a6c2fb0dbe689a8664b552830399329 /unit_trace/viz/schedule.py
parentee7ae82ae6df1378203957b7fa77066153e13c36 (diff)
Significant performance improvements in the graphical rendering, as
well as the eradication of several bugs Also, visualizer is now integrated into the main unit-trace command line tool (use -v option) Note that files are now taken in from the command line, no longer from the GUI
Diffstat (limited to 'unit_trace/viz/schedule.py')
-rw-r--r--unit_trace/viz/schedule.py236
1 files changed, 148 insertions, 88 deletions
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py
index 4277f1a..5efee7d 100644
--- a/unit_trace/viz/schedule.py
+++ b/unit_trace/viz/schedule.py
@@ -11,6 +11,7 @@ import util
11import copy 11import copy
12 12
13EVENT_LIST = None 13EVENT_LIST = None
14SPAN_EVENTS = None
14 15
15class TimeSlotArray(object): 16class TimeSlotArray(object):
16 """Represents another way of organizing the events. This structure organizes events by 17 """Represents another way of organizing the events. This structure organizes events by
@@ -55,20 +56,47 @@ class TimeSlotArray(object):
55 56
56 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) 57 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event)
57 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) 58 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event)
59
60 if event.__class__ in SPAN_END_EVENTS:
61 self.fill_span_event_from_end(event)
62
63 def fill_span_event_from_end(self, event):
64 start_slot = None
65 if event.corresp_start_event is None:
66 start_slot = self.get_time_slot(event.get_job().get_task().get_schedule().start) - 1
67 else:
68 start_slot = self.get_time_slot(event.corresp_start_event.get_time())
69 end_slot = self.get_time_slot(event.get_time())
70
71 for slot in range(start_slot + 1, end_slot):
72 task_no = event.get_job().get_task().get_task_no()
73 cpu = event.get_cpu()
58 74
59 span_events = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} 75 dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu)
60 76 dummy.corresp_start_event = event.corresp_start_event
61 for span_event in span_events: 77 dummy.corresp_end_event = event
62 if isinstance(event, span_event) and event.corresp_start_event is not None:
63 start_slot = self.get_time_slot(event.corresp_start_event.get_time())
64 end_slot = time_slot
65 for slot in range(start_slot + 1, end_slot):
66 dummy = span_events[span_event](task_no, cpu)
67 dummy.corresp_start_event = event.corresp_start_event
68 dummy.corresp_end_event = event
69 78
70 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) 79 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy)
71 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) 80 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy)
81
82 def fill_span_event_from_start(self, event):
83 end_slot = None
84 if event.corresp_end_event is None:
85 end_slot = self.get_time_slot(event.get_job().get_task().get_schedule().end) + 1
86 else:
87 end_slot = self.get_time_slot(event.corresp_end_event.get_time())
88 start_slot = self.get_time_slot(event.get_time())
89
90 for slot in range(start_slot + 1, end_slot):
91 task_no = event.get_job().get_task().get_task_no()
92 cpu = event.get_cpu()
93
94 dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu)
95 dummy.corresp_start_event = event
96 dummy.corresp_end_event = event.corresp_end_event
97
98 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy)
99 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy)
72 100
73 def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): 101 def iter_over_period(self, start, end, start_no, end_no, list_type, event_types):
74 if self.array is None: 102 if self.array is None:
@@ -142,18 +170,28 @@ class Schedule(object):
142 self.set_time_params(time_per_maj) 170 self.set_time_params(time_per_maj)
143 171
144 # we scan the graph task by task, and job by job 172 # we scan the graph task by task, and job by job
145 switches = {}
146 for event in EVENT_LIST:
147 switches[event] = None
148 for task_no, task in enumerate(self.get_task_list()): 173 for task_no, task in enumerate(self.get_task_list()):
174 switches = {}
175 for event in EVENT_LIST:
176 switches[event] = None
149 cur_cpu = [Event.NO_CPU] 177 cur_cpu = [Event.NO_CPU]
150 for job_no in sorted(task.get_jobs().keys()): 178 for job_no in sorted(task.get_jobs().keys()):
151 job = task.get_jobs()[job_no] 179 job = task.get_jobs()[job_no]
152 for event_time in sorted(job.get_events().keys()): 180 for event_time in sorted(job.get_events().keys()):
153 # could have multiple events at the same time (unlikely but possible) 181 # could have multiple events at the same time (unlikely but possible)
154 for event in job.get_events()[event_time]: 182 for event in job.get_events()[event_time]:
155 #print 'task, job, event:', task.name, job.job_no, event.__class__.__name__ 183 print 'task, job, event:', task.name, job.job_no, event.__class__.__name__
156 event.scan(cur_cpu, switches) 184 event.scan(cur_cpu, switches)
185
186 # What if one of the initial "span events" (switch to or inversion starting) never got a
187 # corresponding end event? Well, then we assume that the end event was simply outside of
188 # the range of whatever we read in. So we need to fill dummies starting from the initial
189 # event all the way to the end of the graph, so that the renderer can see the event no matter
190 # how far the user scrolls to the right.
191 for span_event in SPAN_START_EVENTS:
192 event = switches[span_event]
193 if event is not None:
194 self.time_slot_array.fill_span_event_from_start(event)
157 195
158 def add_task(self, task): 196 def add_task(self, task):
159 if task.name in self.tasks: 197 if task.name in self.tasks:
@@ -311,7 +349,7 @@ class Event(DummyEvent):
311 sched.start = time 349 sched.start = time
312 if sched.end is None or time > sched.end: 350 if sched.end is None or time > sched.end:
313 sched.end = time 351 sched.end = time
314 352
315 sched.get_time_slot_array().add_event_to_time_slot(self) 353 sched.get_time_slot_array().add_event_to_time_slot(self)
316 354
317class ErrorEvent(Event): 355class ErrorEvent(Event):
@@ -387,11 +425,59 @@ class CompleteEvent(Event):
387 else: 425 else:
388 graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 426 graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
389 self.get_cpu(), self.is_selected()) 427 self.get_cpu(), self.is_selected())
428
429class SwitchToEvent(Event):
430 def __init__(self, time, cpu):
431 super(SwitchToEvent, self).__init__(time, cpu)
432 self.layer = Canvas.BOTTOM_LAYER
433 self.corresp_end_event = None
434
435 def __str__(self):
436 if self.corresp_end_event is None:
437 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \
438 + str(self.get_time())
439 return 'Scheduled' + self._common_str() + ', START=' \
440 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
441 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
442
443 def scan(self, cur_cpu, switches):
444 old_cur_cpu = cur_cpu[0]
445 cur_cpu[0] = self.get_cpu()
446 switches[SwitchToEvent] = self
447 self.corresp_end_event = None
390 448
449 if old_cur_cpu != Event.NO_CPU:
450 self.erroneous = True
451 print "currently scheduled somewhere, can't switch to a CPU"
452
453 super(SwitchToEvent, self).scan(cur_cpu, switches)
454
455 def render(self, graph, layer, prev_events, selectable=False):
456 if layer == self.layer:
457 end_time = None
458 clip = None
459 if self.corresp_end_event is None:
460 end_time = self.get_job().get_task().get_schedule().end
461 clip = AlignMode.RIGHT
462 else:
463 end_time = self.corresp_end_event.get_time()
464
465 prev_events[self] = None
466 cpu = self.get_cpu()
467 task_no = self.get_job().get_task().get_task_no()
468 if selectable:
469 graph.add_sel_bar_at_time(self.get_time(), end_time,
470 task_no, cpu, self)
471 else:
472 graph.draw_bar_at_time(self.get_time(), end_time,
473 task_no, cpu, self.get_job().get_job_no(),
474 clip, self.is_selected())
475
391class SwitchAwayEvent(Event): 476class SwitchAwayEvent(Event):
392 def __init__(self, time, cpu): 477 def __init__(self, time, cpu):
393 super(SwitchAwayEvent, self).__init__(time, cpu) 478 super(SwitchAwayEvent, self).__init__(time, cpu)
394 self.layer = Canvas.BOTTOM_LAYER 479 self.layer = Canvas.BOTTOM_LAYER
480 self.corresp_start_event = None
395 481
396 def __str__(self): 482 def __str__(self):
397 if self.corresp_start_event is None: 483 if self.corresp_start_event is None:
@@ -431,63 +517,19 @@ class SwitchAwayEvent(Event):
431 prev_events[self] = None 517 prev_events[self] = None
432 cpu = self.get_cpu() 518 cpu = self.get_cpu()
433 task_no = self.get_job().get_task().get_task_no() 519 task_no = self.get_job().get_task().get_task_no()
520 start = self.get_job().get_task().get_schedule().start
434 if selectable: 521 if selectable:
435 start = self.get_job().get_task().get_schedule().start
436 graph.add_sel_bar_at_time(start, self.get_time(), 522 graph.add_sel_bar_at_time(start, self.get_time(),
437 task_no, cpu, self) 523 task_no, cpu, self)
438 else: 524 else:
439 graph.draw_bar_at_time(start, self.get_time(), 525 graph.draw_bar_at_time(start, self.get_time(),
440 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 526 task_no, cpu, self.get_job().get_job_no(),
527 AlignMode.LEFT, self.is_selected())
441 else: 528 else:
442 if self.corresp_start_event in prev_events: 529 if self.corresp_start_event in prev_events:
443 return # already rendered the bar 530 return # already rendered the bar
444 self.corresp_start_event.render(graph, layer, prev_events, selectable) 531 self.corresp_start_event.render(graph, layer, prev_events, selectable)
445 532
446class SwitchToEvent(Event):
447 def __init__(self, time, cpu):
448 super(SwitchToEvent, self).__init__(time, cpu)
449 self.layer = Canvas.BOTTOM_LAYER
450
451 def __str__(self):
452 if self.corresp_end_event is None:
453 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \
454 + str(self.get_time())
455 return 'Scheduled' + self._common_str() + ', START=' \
456 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
457 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
458
459 def scan(self, cur_cpu, switches):
460 old_cur_cpu = cur_cpu[0]
461 cur_cpu[0] = self.get_cpu()
462 switches[SwitchToEvent] = self
463 self.corresp_end_event = None
464
465 if old_cur_cpu != Event.NO_CPU:
466 self.erroneous = True
467 print "currently scheduled somewhere, can't switch to a CPU"
468
469 super(SwitchToEvent, self).scan(cur_cpu, switches)
470
471 def render(self, graph, layer, prev_events, selectable=False):
472 if self.corresp_end_event is None:
473 return # fatally erroneous switch to
474 if layer == self.layer:
475 end_time = None
476 if self.corresp_end_event is None:
477 end_time = self.get_job().get_task().get_schedule().end
478 else:
479 end_time = self.corresp_end_event.get_time()
480
481 prev_events[self] = None
482 cpu = self.get_cpu()
483 task_no = self.get_job().get_task().get_task_no()
484 if selectable:
485 graph.add_sel_bar_at_time(self.get_time(), end_time,
486 task_no, cpu, self)
487 else:
488 graph.draw_bar_at_time(self.get_time(), end_time,
489 task_no, cpu, self.get_job().get_job_no(), self.is_selected())
490
491class ReleaseEvent(Event): 533class ReleaseEvent(Event):
492 def __init__(self, time, cpu): 534 def __init__(self, time, cpu):
493 super(ReleaseEvent, self).__init__(time, cpu) 535 super(ReleaseEvent, self).__init__(time, cpu)
@@ -536,6 +578,7 @@ class InversionStartEvent(ErrorEvent):
536 def __init__(self, time): 578 def __init__(self, time):
537 super(InversionStartEvent, self).__init__(time, Event.NO_CPU) 579 super(InversionStartEvent, self).__init__(time, Event.NO_CPU)
538 self.layer = Canvas.BOTTOM_LAYER 580 self.layer = Canvas.BOTTOM_LAYER
581 self.corresp_end_event = None
539 582
540 def __str__(self): 583 def __str__(self):
541 if self.corresp_end_event is None: 584 if self.corresp_end_event is None:
@@ -553,28 +596,33 @@ class InversionStartEvent(ErrorEvent):
553 super(InversionStartEvent, self).scan(cur_cpu, switches) 596 super(InversionStartEvent, self).scan(cur_cpu, switches)
554 597
555 def render(self, graph, layer, prev_events, selectable=False): 598 def render(self, graph, layer, prev_events, selectable=False):
556 end_time = None
557 if self.corresp_end_event is None:
558 end_time = self.get_job().get_task().get_schedule().end
559 else:
560 end_time = self.corresp_end_event.get_time()
561
562 if layer == self.layer: 599 if layer == self.layer:
563 prev_events[self] = None 600 end_time = None
564 cpu = self.get_cpu() 601 clip = None
565 task_no = self.get_job().get_task().get_task_no() 602 if self.corresp_end_event is None:
566 if selectable: 603 end_time = self.get_job().get_task().get_schedule().end
567 graph.add_sel_mini_bar_at_time(self.get_time(), end_time, 604 clip = AlignMode.RIGHT
568 task_no, cpu, self)
569 else: 605 else:
570 graph.draw_mini_bar_at_time(self.get_time(), end_time, 606 end_time = self.corresp_end_event.get_time()
571 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 607
608 if layer == self.layer:
609 prev_events[self] = None
610 cpu = self.get_cpu()
611 task_no = self.get_job().get_task().get_task_no()
612 if selectable:
613 graph.add_sel_mini_bar_at_time(self.get_time(), end_time,
614 task_no, cpu, self)
615 else:
616 graph.draw_mini_bar_at_time(self.get_time(), end_time,
617 task_no, cpu, self.get_job().get_job_no(),
618 clip, self.is_selected())
572 619
573 620
574class InversionEndEvent(ErrorEvent): 621class InversionEndEvent(ErrorEvent):
575 def __init__(self, time): 622 def __init__(self, time):
576 super(InversionEndEvent, self).__init__(time, Event.NO_CPU) 623 super(InversionEndEvent, self).__init__(time, Event.NO_CPU)
577 self.layer = Canvas.BOTTOM_LAYER 624 self.layer = Canvas.BOTTOM_LAYER
625 self.corresp_start_event = None
578 626
579 def __str__(self): 627 def __str__(self):
580 if self.corresp_start_event is None: 628 if self.corresp_start_event is None:
@@ -607,13 +655,14 @@ class InversionEndEvent(ErrorEvent):
607 prev_events[self] = None 655 prev_events[self] = None
608 cpu = self.get_cpu() 656 cpu = self.get_cpu()
609 task_no = self.get_job().get_task().get_task_no() 657 task_no = self.get_job().get_task().get_task_no()
658 start = self.get_job().get_task().get_schedule().start
610 if selectable: 659 if selectable:
611 start = self.get_job().get_task().get_schedule().start
612 graph.add_sel_mini_bar_at_time(start, self.get_time(), 660 graph.add_sel_mini_bar_at_time(start, self.get_time(),
613 task_no, cpu, self) 661 task_no, cpu, self)
614 else: 662 else:
615 graph.draw_mini_bar_at_time(start, self.get_time(), 663 graph.draw_mini_bar_at_time(start, self.get_time(),
616 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 664 task_no, cpu, self.get_job().get_job_no(),
665 AlignMode.LEFT, self.is_selected())
617 else: 666 else:
618 if self.corresp_start_event in prev_events: 667 if self.corresp_start_event in prev_events:
619 return # already rendered the bar 668 return # already rendered the bar
@@ -625,11 +674,14 @@ class InversionDummy(DummyEvent):
625 self.layer = Canvas.BOTTOM_LAYER 674 self.layer = Canvas.BOTTOM_LAYER
626 675
627 def render(self, graph, layer, prev_events, selectable=False): 676 def render(self, graph, layer, prev_events, selectable=False):
628 if self.corresp_start_event is not None and self.corresp_start_event in prev_events: 677 if self.corresp_start_event is None:
629 return # we have already been rendered 678 if self.corresp_end_event in prev_events:
630 if self.corresp_end_event is not None and self.corresp_end_event in prev_events: 679 return # we have already been rendered
631 return 680 self.corresp_end_event.render(graph, layer, prev_events, selectable)
632 self.corresp_start_event.render(graph, layer, prev_events, selectable) 681 else:
682 if self.corresp_start_event in prev_events:
683 return # we have already been rendered
684 self.corresp_start_event.render(graph, layer, prev_events, selectable)
633 685
634class IsRunningDummy(DummyEvent): 686class IsRunningDummy(DummyEvent):
635 def __init__(self, time, cpu): 687 def __init__(self, time, cpu):
@@ -637,12 +689,20 @@ class IsRunningDummy(DummyEvent):
637 self.layer = Canvas.BOTTOM_LAYER 689 self.layer = Canvas.BOTTOM_LAYER
638 690
639 def render(self, graph, layer, prev_events, selectable=False): 691 def render(self, graph, layer, prev_events, selectable=False):
640 if self.corresp_start_event is None or self.corresp_start_event in prev_events: 692 if self.corresp_start_event is None:
641 return # we have already been rendered 693 if self.corresp_end_event in prev_events:
642 self.corresp_start_event.render(graph, layer, prev_events, selectable) 694 return # we have already been rendered
695 self.corresp_end_event.render(graph, layer, prev_events, selectable)
696 else:
697 if self.corresp_start_event in prev_events:
698 return # we have already been rendered
699 self.corresp_start_event.render(graph, layer, prev_events, selectable)
643 700
644EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None, 701EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None,
645 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, 702 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None,
646 DeadlineEvent : None, IsRunningDummy : None, 703 DeadlineEvent : None, IsRunningDummy : None,
647 InversionStartEvent : None, InversionEndEvent : None, 704 InversionStartEvent : None, InversionEndEvent : None,
648 InversionDummy : None} 705 InversionDummy : None}
706
707SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy }
708SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy}