aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/scripts/python/sched-migration.py177
1 files changed, 92 insertions, 85 deletions
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 9d46377f793b..6d7281a7de33 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -28,11 +28,11 @@ from Core import *
28 28
29class RootFrame(wx.Frame): 29class RootFrame(wx.Frame):
30 Y_OFFSET = 100 30 Y_OFFSET = 100
31 CPU_HEIGHT = 100 31 RECT_HEIGHT = 100
32 CPU_SPACE = 50 32 RECT_SPACE = 50
33 EVENT_MARKING_WIDTH = 5 33 EVENT_MARKING_WIDTH = 5
34 34
35 def __init__(self, timeslices, parent = None, id = -1, title = "Migration"): 35 def __init__(self, sched_tracer, title, parent = None, id = -1):
36 wx.Frame.__init__(self, parent, id, title) 36 wx.Frame.__init__(self, parent, id, title)
37 37
38 (self.screen_width, self.screen_height) = wx.GetDisplaySize() 38 (self.screen_width, self.screen_height) = wx.GetDisplaySize()
@@ -40,11 +40,12 @@ class RootFrame(wx.Frame):
40 self.screen_height -= 10 40 self.screen_height -= 10
41 self.zoom = 0.5 41 self.zoom = 0.5
42 self.scroll_scale = 20 42 self.scroll_scale = 20
43 self.timeslices = timeslices 43 self.sched_tracer = sched_tracer
44 (self.ts_start, self.ts_end) = timeslices.interval() 44 self.sched_tracer.set_root_win(self)
45 (self.ts_start, self.ts_end) = sched_tracer.interval()
45 self.update_width_virtual() 46 self.update_width_virtual()
46 self.nr_cpus = timeslices.max_cpu() + 1 47 self.nr_rects = sched_tracer.nr_rectangles() + 1
47 self.height_virtual = RootFrame.Y_OFFSET + (self.nr_cpus * (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE)) 48 self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
48 49
49 # whole window panel 50 # whole window panel
50 self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) 51 self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
@@ -87,69 +88,38 @@ class RootFrame(wx.Frame):
87 (x, y) = self.scroll_start() 88 (x, y) = self.scroll_start()
88 return self.px_to_us(x) 89 return self.px_to_us(x)
89 90
90 def update_rectangle_cpu(self, dc, slice, cpu, offset_time): 91 def paint_rectangle_zone(self, nr, color, top_color, start, end):
91 rq = slice.rqs[cpu] 92 offset_px = self.us_to_px(start - self.ts_start)
92 93 width_px = self.us_to_px(end - self.ts_start)
93 if slice.total_load != 0:
94 load_rate = rq.load() / float(slice.total_load)
95 else:
96 load_rate = 0
97 94
95 offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
96 width_py = RootFrame.RECT_HEIGHT
98 97
99 offset_px = self.us_to_px(slice.start - offset_time) 98 dc = self.dc
100 width_px = self.us_to_px(slice.end - slice.start)
101 (x, y) = self.scroll_start()
102 99
103 if width_px == 0: 100 if top_color is not None:
104 return 101 (r, g, b) = top_color
102 top_color = wx.Colour(r, g, b)
103 brush = wx.Brush(top_color, wx.SOLID)
104 dc.SetBrush(brush)
105 dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
106 width_py -= RootFrame.EVENT_MARKING_WIDTH
107 offset_py += RootFrame.EVENT_MARKING_WIDTH
105 108
106 offset_py = RootFrame.Y_OFFSET + (cpu * (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE)) 109 (r ,g, b) = color
107 width_py = RootFrame.CPU_HEIGHT 110 color = wx.Colour(r, g, b)
108
109 if cpu in slice.event_cpus:
110 rgb = rq.event.color()
111 if rgb is not None:
112 (r, g, b) = rgb
113 color = wx.Colour(r, g, b)
114 brush = wx.Brush(color, wx.SOLID)
115 dc.SetBrush(brush)
116 dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
117 width_py -= RootFrame.EVENT_MARKING_WIDTH
118 offset_py += RootFrame.EVENT_MARKING_WIDTH
119
120 red_power = int(0xff - (0xff * load_rate))
121 color = wx.Colour(0xff, red_power, red_power)
122 brush = wx.Brush(color, wx.SOLID) 111 brush = wx.Brush(color, wx.SOLID)
123 dc.SetBrush(brush) 112 dc.SetBrush(brush)
124 dc.DrawRectangle(offset_px, offset_py, width_px, width_py) 113 dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
125 114
126 def update_rectangles(self, dc, start, end): 115 def update_rectangles(self, dc, start, end):
127 if len(self.timeslices) == 0: 116 start += self.ts_start
128 return 117 end += self.ts_start
129 start += self.timeslices[0].start 118 self.sched_tracer.fill_zone(start, end)
130 end += self.timeslices[0].start
131
132 color = wx.Colour(0, 0, 0)
133 brush = wx.Brush(color, wx.SOLID)
134 dc.SetBrush(brush)
135
136 i = self.timeslices.find_time_slice(start)
137 if i == -1:
138 return
139
140 for i in xrange(i, len(self.timeslices)):
141 timeslice = self.timeslices[i]
142 if timeslice.start > end:
143 return
144
145 for cpu in timeslice.rqs:
146 self.update_rectangle_cpu(dc, timeslice, cpu, self.timeslices[0].start)
147 119
148 def on_paint(self, event): 120 def on_paint(self, event):
149 color = wx.Colour(0xff, 0xff, 0xff)
150 brush = wx.Brush(color, wx.SOLID)
151 dc = wx.PaintDC(self.scroll_panel) 121 dc = wx.PaintDC(self.scroll_panel)
152 dc.SetBrush(brush) 122 self.dc = dc
153 123
154 width = min(self.width_virtual, self.screen_width) 124 width = min(self.width_virtual, self.screen_width)
155 (x, y) = self.scroll_start() 125 (x, y) = self.scroll_start()
@@ -157,45 +127,31 @@ class RootFrame(wx.Frame):
157 end = self.px_to_us(x + width) 127 end = self.px_to_us(x + width)
158 self.update_rectangles(dc, start, end) 128 self.update_rectangles(dc, start, end)
159 129
160 def cpu_from_ypixel(self, y): 130 def rect_from_ypixel(self, y):
161 y -= RootFrame.Y_OFFSET 131 y -= RootFrame.Y_OFFSET
162 cpu = y / (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE) 132 rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
163 height = y % (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE) 133 height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
164 134
165 if cpu < 0 or cpu > self.nr_cpus - 1 or height > RootFrame.CPU_HEIGHT: 135 if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
166 return -1 136 return -1
167 137
168 return cpu 138 return rect
169
170 def update_summary(self, cpu, t):
171 idx = self.timeslices.find_time_slice(t)
172 if idx == -1:
173 return
174
175 ts = self.timeslices[idx]
176 rq = ts.rqs[cpu]
177 raw = "CPU: %d\n" % cpu
178 raw += "Last event : %s\n" % rq.event.__repr__()
179 raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
180 raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
181 raw += "Load = %d\n" % rq.load()
182 for t in rq.tasks:
183 raw += "%s \n" % thread_name(t)
184 139
140 def update_summary(self, txt):
185 if self.txt: 141 if self.txt:
186 self.txt.Destroy() 142 self.txt.Destroy()
187 self.txt = wx.StaticText(self.panel, -1, raw, (0, (self.screen_height / 2) + 50)) 143 self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
188 144
189 145
190 def on_mouse_down(self, event): 146 def on_mouse_down(self, event):
191 (x, y) = event.GetPositionTuple() 147 (x, y) = event.GetPositionTuple()
192 cpu = self.cpu_from_ypixel(y) 148 rect = self.rect_from_ypixel(y)
193 if cpu == -1: 149 if rect == -1:
194 return 150 return
195 151
196 t = self.px_to_us(x) + self.timeslices[0].start 152 t = self.px_to_us(x) + self.ts_start
197 153
198 self.update_summary(cpu, t) 154 self.sched_tracer.mouse_down(rect, t)
199 155
200 156
201 def update_width_virtual(self): 157 def update_width_virtual(self):
@@ -501,13 +457,64 @@ class TimeSliceList(UserList):
501 457
502 return found 458 return found
503 459
460 def set_root_win(self, win):
461 self.root_win = win
462
463 def mouse_down(self, cpu, t):
464 idx = self.find_time_slice(t)
465 if idx == -1:
466 return
467
468 ts = self[idx]
469 rq = ts.rqs[cpu]
470 raw = "CPU: %d\n" % cpu
471 raw += "Last event : %s\n" % rq.event.__repr__()
472 raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
473 raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
474 raw += "Load = %d\n" % rq.load()
475 for t in rq.tasks:
476 raw += "%s \n" % thread_name(t)
477
478 self.root_win.update_summary(raw)
479
480 def update_rectangle_cpu(self, slice, cpu):
481 rq = slice.rqs[cpu]
482
483 if slice.total_load != 0:
484 load_rate = rq.load() / float(slice.total_load)
485 else:
486 load_rate = 0
487
488 red_power = int(0xff - (0xff * load_rate))
489 color = (0xff, red_power, red_power)
490
491 top_color = None
492
493 if cpu in slice.event_cpus:
494 top_color = rq.event.color()
495
496 self.root_win.paint_rectangle_zone(cpu, color, top_color, slice.start, slice.end)
497
498 def fill_zone(self, start, end):
499 i = self.find_time_slice(start)
500 if i == -1:
501 return
502
503 for i in xrange(i, len(self.data)):
504 timeslice = self.data[i]
505 if timeslice.start > end:
506 return
507
508 for cpu in timeslice.rqs:
509 self.update_rectangle_cpu(timeslice, cpu)
510
504 def interval(self): 511 def interval(self):
505 if len(self.data) == 0: 512 if len(self.data) == 0:
506 return (0, 0) 513 return (0, 0)
507 514
508 return (self.data[0].start, self.data[-1].end) 515 return (self.data[0].start, self.data[-1].end)
509 516
510 def max_cpu(self): 517 def nr_rectangles(self):
511 last_ts = self.data[-1] 518 last_ts = self.data[-1]
512 max_cpu = 0 519 max_cpu = 0
513 for cpu in last_ts.rqs: 520 for cpu in last_ts.rqs:
@@ -557,7 +564,7 @@ def trace_begin():
557def trace_end(): 564def trace_end():
558 app = wx.App(False) 565 app = wx.App(False)
559 timeslices = parser.timeslices 566 timeslices = parser.timeslices
560 frame = RootFrame(timeslices) 567 frame = RootFrame(timeslices, "Migration")
561 app.MainLoop() 568 app.MainLoop()
562 569
563def sched__sched_stat_runtime(event_name, context, common_cpu, 570def sched__sched_stat_runtime(event_name, context, common_cpu,