Export the GUI facility in the common library path. It is going to be useful for other scheduler views.
Showing the changes to tools/perf/scripts/python (2 of 2 files). Show all
Unified · Split
| @@ -0,0 +1,184 @@ | ||
| 1 | +# SchedGui.py - Python extension for perf trace, basic GUI code for | |
| 2 | +# traces drawing and overview. | |
| 3 | +# | |
| 4 | +# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com> | |
| 5 | +# | |
| 6 | +# This software is distributed under the terms of the GNU General | |
| 7 | +# Public License ("GPL") version 2 as published by the Free Software | |
| 8 | +# Foundation. | |
| 9 | + | |
| 10 | + | |
| 11 | +try: | |
| 12 | + import wx | |
| 13 | +except ImportError: | |
| 14 | + raise ImportError, "You need to install the wxpython lib for this script" | |
| 15 | + | |
| 16 | + | |
| 17 | +class RootFrame(wx.Frame): | |
| 18 | + Y_OFFSET = 100 | |
| 19 | + RECT_HEIGHT = 100 | |
| 20 | + RECT_SPACE = 50 | |
| 21 | + EVENT_MARKING_WIDTH = 5 | |
| 22 | + | |
| 23 | + def __init__(self, sched_tracer, title, parent = None, id = -1): | |
| 24 | + wx.Frame.__init__(self, parent, id, title) | |
| 25 | + | |
| 26 | + (self.screen_width, self.screen_height) = wx.GetDisplaySize() | |
| 27 | + self.screen_width -= 10 | |
| 28 | + self.screen_height -= 10 | |
| 29 | + self.zoom = 0.5 | |
| 30 | + self.scroll_scale = 20 | |
| 31 | + self.sched_tracer = sched_tracer | |
| 32 | + self.sched_tracer.set_root_win(self) | |
| 33 | + (self.ts_start, self.ts_end) = sched_tracer.interval() | |
| 34 | + self.update_width_virtual() | |
| 35 | + self.nr_rects = sched_tracer.nr_rectangles() + 1 | |
| 36 | + self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) | |
| 37 | + | |
| 38 | + # whole window panel | |
| 39 | + self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) | |
| 40 | + | |
| 41 | + # scrollable container | |
| 42 | + self.scroll = wx.ScrolledWindow(self.panel) | |
| 43 | + self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale) | |
| 44 | + self.scroll.EnableScrolling(True, True) | |
| 45 | + self.scroll.SetFocus() | |
| 46 | + | |
| 47 | + # scrollable drawing area | |
| 48 | + self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2)) | |
| 49 | + self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint) | |
| 50 | + self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press) | |
| 51 | + self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) | |
| 52 | + self.scroll.Bind(wx.EVT_PAINT, self.on_paint) | |
| 53 | + self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press) | |
| 54 | + self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) | |
| 55 | + | |
| 56 | + self.scroll.Fit() | |
| 57 | + self.Fit() | |
| 58 | + | |
| 59 | + self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING) | |
| 60 | + | |
| 61 | + self.txt = None | |
| 62 | + | |
| 63 | + self.Show(True) | |
| 64 | + | |
| 65 | + def us_to_px(self, val): | |
| 66 | + return val / (10 ** 3) * self.zoom | |
| 67 | + | |
| 68 | + def px_to_us(self, val): | |
| 69 | + return (val / self.zoom) * (10 ** 3) | |
| 70 | + | |
| 71 | + def scroll_start(self): | |
| 72 | + (x, y) = self.scroll.GetViewStart() | |
| 73 | + return (x * self.scroll_scale, y * self.scroll_scale) | |
| 74 | + | |
| 75 | + def scroll_start_us(self): | |
| 76 | + (x, y) = self.scroll_start() | |
| 77 | + return self.px_to_us(x) | |
| 78 | + | |
| 79 | + def paint_rectangle_zone(self, nr, color, top_color, start, end): | |
| 80 | + offset_px = self.us_to_px(start - self.ts_start) | |
| 81 | + width_px = self.us_to_px(end - self.ts_start) | |
| 82 | + | |
| 83 | + offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) | |
| 84 | + width_py = RootFrame.RECT_HEIGHT | |
| 85 | + | |
| 86 | + dc = self.dc | |
| 87 | + | |
| 88 | + if top_color is not None: | |
| 89 | + (r, g, b) = top_color | |
| 90 | + top_color = wx.Colour(r, g, b) | |
| 91 | + brush = wx.Brush(top_color, wx.SOLID) | |
| 92 | + dc.SetBrush(brush) | |
| 93 | + dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH) | |
| 94 | + width_py -= RootFrame.EVENT_MARKING_WIDTH | |
| 95 | + offset_py += RootFrame.EVENT_MARKING_WIDTH | |
| 96 | + | |
| 97 | + (r ,g, b) = color | |
| 98 | + color = wx.Colour(r, g, b) | |
| 99 | + brush = wx.Brush(color, wx.SOLID) | |
| 100 | + dc.SetBrush(brush) | |
| 101 | + dc.DrawRectangle(offset_px, offset_py, width_px, width_py) | |
| 102 | + | |
| 103 | + def update_rectangles(self, dc, start, end): | |
| 104 | + start += self.ts_start | |
| 105 | + end += self.ts_start | |
| 106 | + self.sched_tracer.fill_zone(start, end) | |
| 107 | + | |
| 108 | + def on_paint(self, event): | |
| 109 | + dc = wx.PaintDC(self.scroll_panel) | |
| 110 | + self.dc = dc | |
| 111 | + | |
| 112 | + width = min(self.width_virtual, self.screen_width) | |
| 113 | + (x, y) = self.scroll_start() | |
| 114 | + start = self.px_to_us(x) | |
| 115 | + end = self.px_to_us(x + width) | |
| 116 | + self.update_rectangles(dc, start, end) | |
| 117 | + | |
| 118 | + def rect_from_ypixel(self, y): | |
| 119 | + y -= RootFrame.Y_OFFSET | |
| 120 | + rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) | |
| 121 | + height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) | |
| 122 | + | |
| 123 | + if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT: | |
| 124 | + return -1 | |
| 125 | + | |
| 126 | + return rect | |
| 127 | + | |
| 128 | + def update_summary(self, txt): | |
| 129 | + if self.txt: | |
| 130 | + self.txt.Destroy() | |
| 131 | + self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50)) | |
| 132 | + | |
| 133 | + | |
| 134 | + def on_mouse_down(self, event): | |
| 135 | + (x, y) = event.GetPositionTuple() | |
| 136 | + rect = self.rect_from_ypixel(y) | |
| 137 | + if rect == -1: | |
| 138 | + return | |
| 139 | + | |
| 140 | + t = self.px_to_us(x) + self.ts_start | |
| 141 | + | |
| 142 | + self.sched_tracer.mouse_down(rect, t) | |
| 143 | + | |
| 144 | + | |
| 145 | + def update_width_virtual(self): | |
| 146 | + self.width_virtual = self.us_to_px(self.ts_end - self.ts_start) | |
| 147 | + | |
| 148 | + def __zoom(self, x): | |
| 149 | + self.update_width_virtual() | |
| 150 | + (xpos, ypos) = self.scroll.GetViewStart() | |
| 151 | + xpos = self.us_to_px(x) / self.scroll_scale | |
| 152 | + self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos) | |
| 153 | + self.Refresh() | |
| 154 | + | |
| 155 | + def zoom_in(self): | |
| 156 | + x = self.scroll_start_us() | |
| 157 | + self.zoom *= 2 | |
| 158 | + self.__zoom(x) | |
| 159 | + | |
| 160 | + def zoom_out(self): | |
| 161 | + x = self.scroll_start_us() | |
| 162 | + self.zoom /= 2 | |
| 163 | + self.__zoom(x) | |
| 164 | + | |
| 165 | + | |
| 166 | + def on_key_press(self, event): | |
| 167 | + key = event.GetRawKeyCode() | |
| 168 | + if key == ord("+"): | |
| 169 | + self.zoom_in() | |
| 170 | + return | |
| 171 | + if key == ord("-"): | |
| 172 | + self.zoom_out() | |
| 173 | + return | |
| 174 | + | |
| 175 | + key = event.GetKeyCode() | |
| 176 | + (x, y) = self.scroll.GetViewStart() | |
| 177 | + if key == wx.WXK_RIGHT: | |
| 178 | + self.scroll.Scroll(x + 1, y) | |
| 179 | + elif key == wx.WXK_LEFT: | |
| 180 | + self.scroll.Scroll(x - 1, y) | |
| 181 | + elif key == wx.WXK_DOWN: | |
| 182 | + self.scroll.Scroll(x, y + 1) | |
| 183 | + elif key == wx.WXK_UP: | |
| 184 | + self.scroll.Scroll(x, y - 1) | |
| @@ -6,14 +6,11 @@ · 5 unmodified lines | ||
| 6 | 6 | # |
| 7 | 7 | # perf trace event handlers have been generated by perf trace -g python |
| 8 | 8 | # |
| 9 | −# The whole is licensed under the terms of the GNU GPL License version 2 | |
| 9 | +# This software is distributed under the terms of the GNU General | |
| 10 | +# Public License ("GPL") version 2 as published by the Free Software | |
| 11 | +# Foundation. | |
| 10 | 12 | |
| 11 | 13 | |
| 12 | −try: | |
| 13 | − import wx | |
| 14 | −except ImportError: | |
| 15 | − raise ImportError, "You need to install the wxpython lib for this script" | |
| 16 | − | |
| 17 | 14 | import os |
| 18 | 15 | import sys |
| 19 | 16 | |
| @@ -22,178 +19,11 @@ from UserList import UserList · 2 unmodified lines | ||
| 22 | 19 | |
| 23 | 20 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ |
| 24 | 21 | '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') |
| 22 | +sys.path.append('scripts/python/Perf-Trace-Util/lib/Perf/Trace') | |
| 25 | 23 | |
| 26 | 24 | from perf_trace_context import * |
| 27 | 25 | from Core import * |
| 28 | − | |
| 29 | −class RootFrame(wx.Frame): | |
| 30 | − Y_OFFSET = 100 | |
| 31 | − RECT_HEIGHT = 100 | |
| 32 | − RECT_SPACE = 50 | |
| 33 | − EVENT_MARKING_WIDTH = 5 | |
| 34 | − | |
| 35 | − def __init__(self, sched_tracer, title, parent = None, id = -1): | |
| 36 | − wx.Frame.__init__(self, parent, id, title) | |
| 37 | − | |
| 38 | − (self.screen_width, self.screen_height) = wx.GetDisplaySize() | |
| 39 | − self.screen_width -= 10 | |
| 40 | − self.screen_height -= 10 | |
| 41 | − self.zoom = 0.5 | |
| 42 | − self.scroll_scale = 20 | |
| 43 | − self.sched_tracer = sched_tracer | |
| 44 | − self.sched_tracer.set_root_win(self) | |
| 45 | − (self.ts_start, self.ts_end) = sched_tracer.interval() | |
| 46 | − self.update_width_virtual() | |
| 47 | − self.nr_rects = sched_tracer.nr_rectangles() + 1 | |
| 48 | − self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) | |
| 49 | − | |
| 50 | − # whole window panel | |
| 51 | − self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) | |
| 52 | − | |
| 53 | − # scrollable container | |
| 54 | − self.scroll = wx.ScrolledWindow(self.panel) | |
| 55 | − self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale) | |
| 56 | − self.scroll.EnableScrolling(True, True) | |
| 57 | − self.scroll.SetFocus() | |
| 58 | − | |
| 59 | − # scrollable drawing area | |
| 60 | − self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2)) | |
| 61 | − self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint) | |
| 62 | − self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press) | |
| 63 | − self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) | |
| 64 | − self.scroll.Bind(wx.EVT_PAINT, self.on_paint) | |
| 65 | − self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press) | |
| 66 | − self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) | |
| 67 | − | |
| 68 | − self.scroll.Fit() | |
| 69 | − self.Fit() | |
| 70 | − | |
| 71 | − self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING) | |
| 72 | − | |
| 73 | − self.txt = None | |
| 74 | − | |
| 75 | − self.Show(True) | |
| 76 | − | |
| 77 | − def us_to_px(self, val): | |
| 78 | − return val / (10 ** 3) * self.zoom | |
| 79 | − | |
| 80 | − def px_to_us(self, val): | |
| 81 | − return (val / self.zoom) * (10 ** 3) | |
| 82 | − | |
| 83 | − def scroll_start(self): | |
| 84 | − (x, y) = self.scroll.GetViewStart() | |
| 85 | − return (x * self.scroll_scale, y * self.scroll_scale) | |
| 86 | − | |
| 87 | − def scroll_start_us(self): | |
| 88 | − (x, y) = self.scroll_start() | |
| 89 | − return self.px_to_us(x) | |
| 90 | − | |
| 91 | − def paint_rectangle_zone(self, nr, color, top_color, start, end): | |
| 92 | − offset_px = self.us_to_px(start - self.ts_start) | |
| 93 | − width_px = self.us_to_px(end - self.ts_start) | |
| 94 | − | |
| 95 | − offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) | |
| 96 | − width_py = RootFrame.RECT_HEIGHT | |
| 97 | − | |
| 98 | − dc = self.dc | |
| 99 | − | |
| 100 | − if top_color is not None: | |
| 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 | |
| 108 | − | |
| 109 | − (r ,g, b) = color | |
| 110 | − color = wx.Colour(r, g, b) | |
| 111 | − brush = wx.Brush(color, wx.SOLID) | |
| 112 | − dc.SetBrush(brush) | |
| 113 | − dc.DrawRectangle(offset_px, offset_py, width_px, width_py) | |
| 114 | − | |
| 115 | − def update_rectangles(self, dc, start, end): | |
| 116 | − start += self.ts_start | |
| 117 | − end += self.ts_start | |
| 118 | − self.sched_tracer.fill_zone(start, end) | |
| 119 | − | |
| 120 | − def on_paint(self, event): | |
| 121 | − dc = wx.PaintDC(self.scroll_panel) | |
| 122 | − self.dc = dc | |
| 123 | − | |
| 124 | − width = min(self.width_virtual, self.screen_width) | |
| 125 | − (x, y) = self.scroll_start() | |
| 126 | − start = self.px_to_us(x) | |
| 127 | − end = self.px_to_us(x + width) | |
| 128 | − self.update_rectangles(dc, start, end) | |
| 129 | − | |
| 130 | − def rect_from_ypixel(self, y): | |
| 131 | − y -= RootFrame.Y_OFFSET | |
| 132 | − rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) | |
| 133 | − height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) | |
| 134 | − | |
| 135 | − if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT: | |
| 136 | − return -1 | |
| 137 | − | |
| 138 | − return rect | |
| 139 | − | |
| 140 | − def update_summary(self, txt): | |
| 141 | − if self.txt: | |
| 142 | − self.txt.Destroy() | |
| 143 | − self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50)) | |
| 144 | − | |
| 145 | − | |
| 146 | − def on_mouse_down(self, event): | |
| 147 | − (x, y) = event.GetPositionTuple() | |
| 148 | − rect = self.rect_from_ypixel(y) | |
| 149 | − if rect == -1: | |
| 150 | − return | |
| 151 | − | |
| 152 | − t = self.px_to_us(x) + self.ts_start | |
| 153 | − | |
| 154 | − self.sched_tracer.mouse_down(rect, t) | |
| 155 | − | |
| 156 | − | |
| 157 | − def update_width_virtual(self): | |
| 158 | − self.width_virtual = self.us_to_px(self.ts_end - self.ts_start) | |
| 159 | − | |
| 160 | − def __zoom(self, x): | |
| 161 | − self.update_width_virtual() | |
| 162 | − (xpos, ypos) = self.scroll.GetViewStart() | |
| 163 | − xpos = self.us_to_px(x) / self.scroll_scale | |
| 164 | − self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos) | |
| 165 | − self.Refresh() | |
| 166 | − | |
| 167 | − def zoom_in(self): | |
| 168 | − x = self.scroll_start_us() | |
| 169 | − self.zoom *= 2 | |
| 170 | − self.__zoom(x) | |
| 171 | − | |
| 172 | − def zoom_out(self): | |
| 173 | − x = self.scroll_start_us() | |
| 174 | − self.zoom /= 2 | |
| 175 | − self.__zoom(x) | |
| 176 | − | |
| 177 | − | |
| 178 | − def on_key_press(self, event): | |
| 179 | − key = event.GetRawKeyCode() | |
| 180 | − if key == ord("+"): | |
| 181 | − self.zoom_in() | |
| 182 | − return | |
| 183 | − if key == ord("-"): | |
| 184 | − self.zoom_out() | |
| 185 | − return | |
| 186 | − | |
| 187 | − key = event.GetKeyCode() | |
| 188 | − (x, y) = self.scroll.GetViewStart() | |
| 189 | − if key == wx.WXK_RIGHT: | |
| 190 | − self.scroll.Scroll(x + 1, y) | |
| 191 | − elif key == wx.WXK_LEFT: | |
| 192 | − self.scroll.Scroll(x - 1, y) | |
| 193 | − elif key == wx.WXK_DOWN: | |
| 194 | − self.scroll.Scroll(x, y + 1) | |
| 195 | − elif key == wx.WXK_UP: | |
| 196 | − self.scroll.Scroll(x, y - 1) | |
| 26 | +from SchedGui import * | |
| 197 | 27 | |
| 198 | 28 | |
| 199 | 29 | threads = { 0 : "idle"} |