tools: in performance-log-viewer.py, visualize percentage in profile viewer

In the performance-log viewer's profile view, displasy in-line bar-
chart-like visualization of function and source-line sample
percentages, as part of the corresponding tree-view cells.
This commit is contained in:
Ell 2018-10-19 10:02:04 -04:00
parent 2987f012f9
commit 26ea334825
1 changed files with 143 additions and 37 deletions

View File

@ -47,9 +47,7 @@ def format_float (x):
return "%g" % (round (100 * x) / 100)
def format_percentage (x, digits = 0):
scale = 10 ** digits
return "%g%%" % (round (100 * scale * x) / scale)
return "%%.%df%%%%" % digits % (100 * x)
def format_size (size):
return GLib.format_size_full (size, GLib.FormatSizeFlags.IEC_UNITS)
@ -68,6 +66,35 @@ def format_color (color):
def is_bright_color (color):
return max (tuple (color)[0:3]) > 0.5
def blend_colors (color1, color2, amount):
color1 = tuple (color1)
color2 = tuple (color2)
a1 = color1[-1]
a2 = color2[-1]
a = (1 - amount) * a1 + amount * a2
return tuple (a and ((1 - amount) * a1 * c1 + amount * a2 * c2) / a
for c1, c2 in zip (color1[:-1], color2[:-1])) + (a,)
def rounded_rectangle (cr, x, y, width, height, radius):
radius = min (radius, width / 2, height / 2)
cr.arc (x + radius, y + radius, radius, -math.pi, -math.pi / 2)
cr.rel_line_to (width - 2 * radius, 0)
cr.arc (x + width - radius, y + radius, radius, -math.pi / 2, 0)
cr.rel_line_to (0, height - 2 * radius)
cr.arc (x + width - radius, y + height - radius, radius, 0, math.pi / 2)
cr.rel_line_to (-(width - 2 * radius), 0)
cr.arc (x + radius, y + height - radius, radius, math.pi / 2, math.pi)
cr.rel_line_to (0, -(height - 2 * radius))
cr.close_path ()
def get_basename (path):
match = re.fullmatch (".*[\\\\/](.+?)[\\\\/]?", path)
@ -2174,6 +2201,90 @@ class BacktraceViewer (Gtk.Box):
return False
class CellRendererPercentage (Gtk.CellRendererText):
padding = 0
def __init__ (self, *args, **kwargs):
Gtk.CellRendererText.__init__ (self, *args, xalign = 1, **kwargs)
self.value = 0
@GObject.property (type = float)
def value (self):
return self.value_property
@value.setter
def value (self, value):
self.value_property = value
self.set_property ("text", format_percentage (value, 2))
def do_render (self, cr, widget, background_area, cell_area, flags):
full_width = cell_area.width - 2 * self.padding
full_height = cell_area.height - 2 * self.padding
if full_width <= 0 or full_height <= 0:
return
state = widget.get_state ()
style = widget.get_style_context ()
fg_color = style.get_color (state)
rounded_rectangle (cr,
cell_area.x + self.padding,
cell_area.y + self.padding,
full_width,
full_height,
1)
cr.clip ()
cr.set_source_rgba (*blend_colors ((0, 0, 0, 0), fg_color, 0.2))
cr.paint ()
Gtk.CellRendererText.do_render (self,
cr, widget,
background_area, cell_area,
Gtk.CellRendererState (
flags |
Gtk.CellRendererState.SELECTED
))
value = min (max (self.value, 0), 1)
width = round (full_width * value)
height = full_height
if width > 0 and height > 0:
state = Gtk.StateFlags (state | Gtk.StateFlags.SELECTED)
style.save ()
style.set_state (state)
fg_color = style.get_color (state)
bg_color = style.get_background_color (state)
x = round ((full_width - width) * self.get_property ("xalign"))
cr.rectangle (cell_area.x + self.padding + x,
cell_area.y + self.padding,
width,
height)
cr.clip ()
cr.set_source_rgba (*blend_colors (bg_color, fg_color, -0.3))
cr.paint ()
Gtk.CellRendererText.do_render (self,
cr, widget,
background_area, cell_area,
Gtk.CellRendererState (
flags |
Gtk.CellRendererState.SELECTED
))
style.restore ()
class ProfileViewer (Gtk.ScrolledWindow):
class ThreadFilter (Gtk.TreeView):
class Store (Gtk.ListStore):
@ -2468,29 +2579,23 @@ class ProfileViewer (Gtk.ScrolledWindow):
col.add_attribute (cell, "text", store.FUNCTION)
cell.set_property ("width-chars", 40)
def format_percentage_col (tree_col, cell, model, iter, col):
cell.set_property ("text",
format_percentage (model[iter][col], 2))
col = Gtk.TreeViewColumn (title = "Self")
tree.append_column (col)
col.set_alignment (0.5)
col.set_sort_column_id (store.EXCLUSIVE)
cell = Gtk.CellRendererText (xalign = 1)
cell = CellRendererPercentage ()
col.pack_start (cell, False)
col.set_cell_data_func (cell,
format_percentage_col, store.EXCLUSIVE)
col.add_attribute (cell, "value", store.EXCLUSIVE)
col = Gtk.TreeViewColumn (title = "All")
tree.append_column (col)
col.set_alignment (0.5)
col.set_sort_column_id (store.INCLUSIVE)
cell = Gtk.CellRendererText (xalign = 1)
cell = CellRendererPercentage ()
col.pack_start (cell, False)
col.set_cell_data_func (cell,
format_percentage_col, store.INCLUSIVE)
col.add_attribute (cell, "value", store.INCLUSIVE)
if id:
self.update ()
@ -2798,13 +2903,14 @@ class ProfileViewer (Gtk.ScrolledWindow):
class SourceProfile (Gtk.Box):
class Store (Gtk.ListStore):
LINE = 0
EXCLUSIVE = 1
INCLUSIVE = 2
TEXT = 3
LINE = 0
HAS_FRAMES = 1
EXCLUSIVE = 2
INCLUSIVE = 3
TEXT = 4
def __init__ (self):
Gtk.ListStore.__init__ (self, int, float, float, str)
Gtk.ListStore.__init__ (self, int, bool, float, float, str)
__gsignals__ = {
"subprofile-added": (GObject.SIGNAL_RUN_FIRST,
@ -2894,33 +3000,25 @@ class ProfileViewer (Gtk.ScrolledWindow):
scale = 0.85
def format_percentage_col (tree_col, cell, model, iter, col):
value = model[iter][col]
if value >= 0:
cell.set_property ("text", format_percentage (value, 2))
else:
cell.set_property ("text", "")
col = Gtk.TreeViewColumn (title = "Self")
tree.append_column (col)
col.set_alignment (0.5)
col.set_sort_column_id (store.EXCLUSIVE)
cell = Gtk.CellRendererText (xalign = 1, scale = scale)
cell = CellRendererPercentage (scale = scale)
col.pack_start (cell, False)
col.set_cell_data_func (cell,
format_percentage_col, store.EXCLUSIVE)
col.add_attribute (cell, "visible", store.HAS_FRAMES)
col.add_attribute (cell, "value", store.EXCLUSIVE)
col = Gtk.TreeViewColumn (title = "All")
tree.append_column (col)
col.set_alignment (0.5)
col.set_sort_column_id (store.INCLUSIVE)
cell = Gtk.CellRendererText (xalign = 1, scale = scale)
cell = CellRendererPercentage (scale = scale)
col.pack_start (cell, False)
col.set_cell_data_func (cell,
format_percentage_col, store.INCLUSIVE)
col.add_attribute (cell, "visible", store.HAS_FRAMES)
col.add_attribute (cell, "value", store.INCLUSIVE)
col = Gtk.TreeViewColumn ()
tree.append_column (col)
@ -2998,12 +3096,20 @@ class ProfileViewer (Gtk.ScrolledWindow):
for text in open (self.file.get_path (), "r"):
text = text.rstrip ("\n")
line = lines.get (i, [-1, -1])
line = lines.get (i, None)
self.store.append ((i,
line[0] / n_stacks,
line[1] / n_stacks,
text))
if line:
self.store.append ((i,
True,
line[0] / n_stacks,
line[1] / n_stacks,
text))
else:
self.store.append ((i,
False,
0,
0,
text))
i += 1