aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2010-07-25 20:02:39 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2010-08-01 19:31:58 -0400
commit699b6d922c7d07f0c1c9041b489e884b5dd5fee5 (patch)
treea4d27c2288685c6bac5ca68366dfef6966e9d1ba /tools/perf/scripts
parent70d815a3decc57c482e5384a623a859e3371e680 (diff)
perf, sched migration: Make the GUI class client agnostic
Make the perf migration GUI generic so that it can be reused for other kinds of trace painting. No more notion of CPUs or runqueue from the GUI class, it's now used as a library by the trace parser. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Nikhil Rao <ncrao@google.com> Cc: Tom Zanussi <tzanussi@gmail.com>
Diffstat (limited to 'tools/perf/scripts')
-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,