diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py index 9d46377f793b098883dc4349ab6dde22b8407dd8..6d7281a7de33a8bcb6ba57df01d7f3164f1135c5 100644 --- a/tools/perf/scripts/python/sched-migration.py +++ b/tools/perf/scripts/python/sched-migration.py @@ -28,11 +28,11 @@ from Core import * class RootFrame(wx.Frame): Y_OFFSET = 100 - CPU_HEIGHT = 100 - CPU_SPACE = 50 + RECT_HEIGHT = 100 + RECT_SPACE = 50 EVENT_MARKING_WIDTH = 5 - def __init__(self, timeslices, parent = None, id = -1, title = "Migration"): + def __init__(self, sched_tracer, title, parent = None, id = -1): wx.Frame.__init__(self, parent, id, title) (self.screen_width, self.screen_height) = wx.GetDisplaySize() @@ -40,11 +40,12 @@ class RootFrame(wx.Frame): self.screen_height -= 10 self.zoom = 0.5 self.scroll_scale = 20 - self.timeslices = timeslices - (self.ts_start, self.ts_end) = timeslices.interval() + self.sched_tracer = sched_tracer + self.sched_tracer.set_root_win(self) + (self.ts_start, self.ts_end) = sched_tracer.interval() self.update_width_virtual() - self.nr_cpus = timeslices.max_cpu() + 1 - self.height_virtual = RootFrame.Y_OFFSET + (self.nr_cpus * (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE)) + self.nr_rects = sched_tracer.nr_rectangles() + 1 + self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) # whole window panel self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) @@ -87,69 +88,38 @@ class RootFrame(wx.Frame): (x, y) = self.scroll_start() return self.px_to_us(x) - def update_rectangle_cpu(self, dc, slice, cpu, offset_time): - rq = slice.rqs[cpu] - - if slice.total_load != 0: - load_rate = rq.load() / float(slice.total_load) - else: - load_rate = 0 + def paint_rectangle_zone(self, nr, color, top_color, start, end): + offset_px = self.us_to_px(start - self.ts_start) + width_px = self.us_to_px(end - self.ts_start) + offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) + width_py = RootFrame.RECT_HEIGHT - offset_px = self.us_to_px(slice.start - offset_time) - width_px = self.us_to_px(slice.end - slice.start) - (x, y) = self.scroll_start() + dc = self.dc - if width_px == 0: - return + if top_color is not None: + (r, g, b) = top_color + top_color = wx.Colour(r, g, b) + brush = wx.Brush(top_color, wx.SOLID) + dc.SetBrush(brush) + dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH) + width_py -= RootFrame.EVENT_MARKING_WIDTH + offset_py += RootFrame.EVENT_MARKING_WIDTH - offset_py = RootFrame.Y_OFFSET + (cpu * (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE)) - width_py = RootFrame.CPU_HEIGHT - - if cpu in slice.event_cpus: - rgb = rq.event.color() - if rgb is not None: - (r, g, b) = rgb - color = wx.Colour(r, g, b) - brush = wx.Brush(color, wx.SOLID) - dc.SetBrush(brush) - dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH) - width_py -= RootFrame.EVENT_MARKING_WIDTH - offset_py += RootFrame.EVENT_MARKING_WIDTH - - red_power = int(0xff - (0xff * load_rate)) - color = wx.Colour(0xff, red_power, red_power) + (r ,g, b) = color + color = wx.Colour(r, g, b) brush = wx.Brush(color, wx.SOLID) dc.SetBrush(brush) dc.DrawRectangle(offset_px, offset_py, width_px, width_py) def update_rectangles(self, dc, start, end): - if len(self.timeslices) == 0: - return - start += self.timeslices[0].start - end += self.timeslices[0].start - - color = wx.Colour(0, 0, 0) - brush = wx.Brush(color, wx.SOLID) - dc.SetBrush(brush) - - i = self.timeslices.find_time_slice(start) - if i == -1: - return - - for i in xrange(i, len(self.timeslices)): - timeslice = self.timeslices[i] - if timeslice.start > end: - return - - for cpu in timeslice.rqs: - self.update_rectangle_cpu(dc, timeslice, cpu, self.timeslices[0].start) + start += self.ts_start + end += self.ts_start + self.sched_tracer.fill_zone(start, end) def on_paint(self, event): - color = wx.Colour(0xff, 0xff, 0xff) - brush = wx.Brush(color, wx.SOLID) dc = wx.PaintDC(self.scroll_panel) - dc.SetBrush(brush) + self.dc = dc width = min(self.width_virtual, self.screen_width) (x, y) = self.scroll_start() @@ -157,45 +127,31 @@ class RootFrame(wx.Frame): end = self.px_to_us(x + width) self.update_rectangles(dc, start, end) - def cpu_from_ypixel(self, y): + def rect_from_ypixel(self, y): y -= RootFrame.Y_OFFSET - cpu = y / (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE) - height = y % (RootFrame.CPU_HEIGHT + RootFrame.CPU_SPACE) + rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) + height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) - if cpu < 0 or cpu > self.nr_cpus - 1 or height > RootFrame.CPU_HEIGHT: + if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT: return -1 - return cpu - - def update_summary(self, cpu, t): - idx = self.timeslices.find_time_slice(t) - if idx == -1: - return - - ts = self.timeslices[idx] - rq = ts.rqs[cpu] - raw = "CPU: %d\n" % cpu - raw += "Last event : %s\n" % rq.event.__repr__() - raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000) - raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6)) - raw += "Load = %d\n" % rq.load() - for t in rq.tasks: - raw += "%s \n" % thread_name(t) + return rect + def update_summary(self, txt): if self.txt: self.txt.Destroy() - self.txt = wx.StaticText(self.panel, -1, raw, (0, (self.screen_height / 2) + 50)) + self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50)) def on_mouse_down(self, event): (x, y) = event.GetPositionTuple() - cpu = self.cpu_from_ypixel(y) - if cpu == -1: + rect = self.rect_from_ypixel(y) + if rect == -1: return - t = self.px_to_us(x) + self.timeslices[0].start + t = self.px_to_us(x) + self.ts_start - self.update_summary(cpu, t) + self.sched_tracer.mouse_down(rect, t) def update_width_virtual(self): @@ -501,13 +457,64 @@ class TimeSliceList(UserList): return found + def set_root_win(self, win): + self.root_win = win + + def mouse_down(self, cpu, t): + idx = self.find_time_slice(t) + if idx == -1: + return + + ts = self[idx] + rq = ts.rqs[cpu] + raw = "CPU: %d\n" % cpu + raw += "Last event : %s\n" % rq.event.__repr__() + raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000) + raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6)) + raw += "Load = %d\n" % rq.load() + for t in rq.tasks: + raw += "%s \n" % thread_name(t) + + self.root_win.update_summary(raw) + + def update_rectangle_cpu(self, slice, cpu): + rq = slice.rqs[cpu] + + if slice.total_load != 0: + load_rate = rq.load() / float(slice.total_load) + else: + load_rate = 0 + + red_power = int(0xff - (0xff * load_rate)) + color = (0xff, red_power, red_power) + + top_color = None + + if cpu in slice.event_cpus: + top_color = rq.event.color() + + self.root_win.paint_rectangle_zone(cpu, color, top_color, slice.start, slice.end) + + def fill_zone(self, start, end): + i = self.find_time_slice(start) + if i == -1: + return + + for i in xrange(i, len(self.data)): + timeslice = self.data[i] + if timeslice.start > end: + return + + for cpu in timeslice.rqs: + self.update_rectangle_cpu(timeslice, cpu) + def interval(self): if len(self.data) == 0: return (0, 0) return (self.data[0].start, self.data[-1].end) - def max_cpu(self): + def nr_rectangles(self): last_ts = self.data[-1] max_cpu = 0 for cpu in last_ts.rqs: @@ -557,7 +564,7 @@ def trace_begin(): def trace_end(): app = wx.App(False) timeslices = parser.timeslices - frame = RootFrame(timeslices) + frame = RootFrame(timeslices, "Migration") app.MainLoop() def sched__sched_stat_runtime(event_name, context, common_cpu,