diff options
author | Eugene Tarassov | 2015-03-06 22:10:13 +0000 |
---|---|---|
committer | Eugene Tarassov | 2015-03-06 22:10:13 +0000 |
commit | bb309f0c6ef8ac75a68ad01b64603e629517f721 (patch) | |
tree | 2f0830ce92e8a5458b17983eccc2d82b49bbe00b /plugins | |
parent | 65a8e283e265383bc0704640c0c066aef240f242 (diff) | |
download | org.eclipse.tcf-bb309f0c6ef8ac75a68ad01b64603e629517f721.tar.gz org.eclipse.tcf-bb309f0c6ef8ac75a68ad01b64603e629517f721.tar.xz org.eclipse.tcf-bb309f0c6ef8ac75a68ad01b64603e629517f721.zip |
TCF Profiler: added bar graph visualization
Diffstat (limited to 'plugins')
2 files changed, 146 insertions, 50 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerSettingsDlg.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerSettingsDlg.java index 6d52e8902..4faa55d6b 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerSettingsDlg.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerSettingsDlg.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Xilinx, Inc. and others. + * Copyright (c) 2013, 2015 Xilinx, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -38,6 +38,7 @@ class ProfilerSettingsDlg extends Dialog { static final String PARAM_VIEW_UPDATE_PERIOD = "ViewUpdatePeriod"; static final String PARAM_AGGREGATE = "Aggregate"; + static final String PARAM_STACK_TRACE = "StackTrace"; Map<String,Object> conf; Map<String,Object> data; @@ -142,29 +143,23 @@ class ProfilerSettingsDlg extends Dialog { } private void setData() { - Boolean b = (Boolean)conf.get(PARAM_AGGREGATE); - aggregate_button.setSelection(b != null && b.booleanValue()); - Number n = (Number)conf.get(IProfiler.PARAM_FRAME_CNT); - if (n == null || n.intValue() <= 1) { - stack_trace_button.setSelection(false); - frame_cnt_text.setText("5"); - } - else { - stack_trace_button.setSelection(true); - frame_cnt_text.setText(conf.get(IProfiler.PARAM_FRAME_CNT).toString()); - } - view_update_text.setText(conf.get(PARAM_VIEW_UPDATE_PERIOD).toString()); + Boolean b_ag = (Boolean)conf.get(PARAM_AGGREGATE); + aggregate_button.setSelection(b_ag != null && b_ag.booleanValue()); + Boolean b_st = (Boolean)conf.get(PARAM_STACK_TRACE); + stack_trace_button.setSelection(b_st != null && b_st.booleanValue()); + Number n_fc = (Number)conf.get(IProfiler.PARAM_FRAME_CNT); + if (n_fc == null) n_fc = Integer.valueOf(1); + frame_cnt_text.setText(n_fc.toString()); + Number n_vu = (Number)conf.get(PARAM_VIEW_UPDATE_PERIOD); + if (n_vu == null) n_vu = Integer.valueOf(1000); + view_update_text.setText(n_vu.toString()); } private void getData() { data = new HashMap<String,Object>(); data.put(PARAM_AGGREGATE, aggregate_button.getSelection()); - if (stack_trace_button.getSelection()) { - data.put(IProfiler.PARAM_FRAME_CNT, new Integer(frame_cnt_text.getText())); - } - else { - data.put(IProfiler.PARAM_FRAME_CNT, 1); - } + data.put(PARAM_STACK_TRACE, stack_trace_button.getSelection()); + data.put(IProfiler.PARAM_FRAME_CNT, new Integer(frame_cnt_text.getText())); data.put(PARAM_VIEW_UPDATE_PERIOD, new Integer(view_update_text.getText())); } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerView.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerView.java index 6bbec2369..dbfcbacce 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerView.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2014 Xilinx, Inc. and others. + * Copyright (c) 2013, 2015 Xilinx, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -41,9 +41,12 @@ import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; @@ -81,9 +84,10 @@ import org.eclipse.ui.part.ViewPart; public class ProfilerView extends ViewPart { - private static final int FRAME_COUNT = 5; + private static final int FRAME_COUNT = 8; private static final String PARAM_VIEW_UPDATE_PERIOD = ProfilerSettingsDlg.PARAM_VIEW_UPDATE_PERIOD; private static final String PARAM_AGGREGATE = ProfilerSettingsDlg.PARAM_AGGREGATE; + private static final String PARAM_STACK_TRACE = ProfilerSettingsDlg.PARAM_STACK_TRACE; private static class ProfileSample { int cnt; @@ -97,6 +101,7 @@ public class ProfilerView extends ViewPart { private static class ProfileData { final String ctx; final Map<String,Object> params; + final boolean stack_trace; boolean stopped; boolean unsupported; @@ -115,8 +120,13 @@ public class ProfilerView extends ViewPart { ProfileData(String ctx, Map<String,Object> params) { this.ctx = ctx; this.params = new HashMap<String,Object>(params); - Number n = (Number)params.get(IProfiler.PARAM_FRAME_CNT); - int frame_cnt = n.intValue(); + Boolean b = (Boolean)params.get(PARAM_STACK_TRACE); + stack_trace = b != null && b.booleanValue(); + int frame_cnt = 1; + if (stack_trace) { + Number n = (Number)params.get(IProfiler.PARAM_FRAME_CNT); + if (n != null) frame_cnt = n.intValue(); + } map = new Map[frame_cnt]; for (int i = 0; i < frame_cnt; i++) { map[i] = new HashMap<BigInteger,List<ProfileSample>>(); @@ -542,6 +552,7 @@ public class ProfilerView extends ViewPart { final boolean stopped = node != null && prof_data.stopped; final boolean running = node != null && !stopped; final boolean unsupported = node != null && prof_data.unsupported; + final boolean total_count = prof_data != null && prof_data.stack_trace; final int sample_count = prof_data == null ? 0 : prof_data.sample_count; final String error_msg = prof_data == null || prof_data.error == null ? null : TCFModel.getErrorMessage(prof_data.error, false); @@ -553,9 +564,11 @@ public class ProfilerView extends ViewPart { action_start.setEnabled(enable_start); action_stop.setEnabled(enable_stop); profile_node = node; + disposeColors(); Object viewer_input = prof_data != null ? prof_data.entries : null; if (viewer_main.getInput() != viewer_input) { ISelection s = viewer_main.getSelection(); + ProfilerView.this.total_count = total_count; ProfilerView.this.sample_count = sample_count; viewer_main.setInput(viewer_input); List<ProfileEntry> l = new ArrayList<ProfileEntry>(); @@ -621,8 +634,8 @@ public class ProfilerView extends ViewPart { ProfileEntry e = (ProfileEntry)element; switch (column) { case 0: return toHex(e.addr); - case 1: return toPercent(e.count); - case 2: return toPercent(e.total); + case 1: return ""; + case 2: return ""; case 3: return e.name; case 4: return e.file_base; case 5: return e.line == 0 ? null : Integer.toString(e.line); @@ -642,7 +655,7 @@ public class ProfilerView extends ViewPart { switch (column) { case 0: return toHex(e.pe.addr); case 1: return ""; - case 2: return toPercent(e.total); + case 2: return ""; case 3: return e.pe.name; case 4: return e.pe.file_base; case 5: return e.pe.line == 0 ? null : Integer.toString(e.pe.line); @@ -651,22 +664,6 @@ public class ProfilerView extends ViewPart { } } - private String toHex(BigInteger n) { - String s = n.toString(16); - if (s.length() >= 8) return s; - return "00000000".substring(s.length()) + s; - } - - private String toPercent(float x) { - float f = x * 100 / sample_count; - if (f >= 100) return "100"; - if (f >= 10) return String.format("%.1f", f); - if (f >= 1) return String.format("%.2f", f); - String s = String.format("%.3f", f); - if (s.charAt(0) == '0') s = s.substring(1); - return s; - } - private final Action action_start = new Action("Start", ImageCache.getImageDescriptor(ImageCache.IMG_THREAD_RUNNNIG)) { @Override public void run() { @@ -720,6 +717,8 @@ public class ProfilerView extends ViewPart { private Composite main_composite; private TCFNode profile_node; private int sample_count; + private boolean total_count; + private HashMap<RGB,Color> colors = new HashMap<RGB,Color>(); private static final String[] column_ids = { "Address", @@ -814,7 +813,7 @@ public class ProfilerView extends ViewPart { selectionChanged(active_context); } - public Composite createTable(Composite parent) { + private Composite createTable(Composite parent) { Font font = parent.getFont(); final Composite composite = new Composite(parent, SWT.NO_FOCUS); final FormLayout layout = new FormLayout(); @@ -889,6 +888,7 @@ public class ProfilerView extends ViewPart { table.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { + disposeColors(); if (e.item == null) return; ProfileEntry pe = (ProfileEntry)viewer_main.getElementAt(table.indexOf((TableItem)e.item)); viewer_up.setInput(pe.up); @@ -899,6 +899,19 @@ public class ProfilerView extends ViewPart { public void widgetDefaultSelected(SelectionEvent e) { } }); + + table.addListener(SWT.PaintItem, new Listener() { + @Override + public void handleEvent(Event event) { + if (event.index == 1 || event.index == 2 && total_count) { + int index = table.indexOf((TableItem)event.item); + ProfileEntry pe = ((ProfileEntry[])viewer_main.getInput())[index]; + float count = event.index == 1 ? (float)pe.count : pe.total; + paintPercent(event, count); + } + } + }); + return composite; } @@ -933,6 +946,17 @@ public class ProfilerView extends ViewPart { } }); + table_up.addListener(SWT.PaintItem, new Listener() { + @Override + public void handleEvent(Event event) { + if (event.index == 2) { + int index = table_up.indexOf((TableItem)event.item); + ProfileEntryRef pe = ((ProfileEntryRef[])viewer_up.getInput())[index]; + paintPercent(event, pe.total); + } + } + }); + final Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); separator.setFont(font); @@ -962,6 +986,17 @@ public class ProfilerView extends ViewPart { } }); + table_dw.addListener(SWT.PaintItem, new Listener() { + @Override + public void handleEvent(Event event) { + if (event.index == 2) { + int index = table_dw.indexOf((TableItem)event.item); + ProfileEntryRef pe = ((ProfileEntryRef[])viewer_dw.getInput())[index]; + paintPercent(event, pe.total); + } + } + }); + for (int i = 0; i < column_ids.length; i++) { createColumn(table_up, i); createColumn(table_dw, i); @@ -1040,7 +1075,7 @@ public class ProfilerView extends ViewPart { int w = c.getWidth(); if (n == column_size.length - 1 && !System.getProperty("os.name", "").startsWith("Windows")) { // Workaround: - // Linux GTK tries to outsmart a user: last column is auto-resized when table size changes. + // Linux GTK tries to outsmart user: last column is auto-resized when table size changes. // This causes infinite recursion and stack overflow. if (w > column_size[n]) w = column_size[n]; } @@ -1062,6 +1097,61 @@ public class ProfilerView extends ViewPart { } } + private String toHex(BigInteger n) { + String s = n.toString(16); + if (s.length() >= 8) return s; + return "00000000".substring(s.length()) + s; + } + + private void disposeColors() { + for (Color c : colors.values()) c.dispose(); + colors.clear(); + } + + private Color getColor(RGB rgb) { + Color c = colors.get(rgb); + if (c == null) { + c = new Color(parent.getDisplay(), rgb); + colors.put(rgb, c); + } + return c; + } + + private String toPercent(float x) { + float f = x * 100 / sample_count; + if (f >= 100) return "100"; + if (f >= 10) return String.format("%.1f", f); + if (f >= 1) return String.format("%.2f", f); + String s = String.format("%.3f", f); + if (s.charAt(0) == '0') s = s.substring(1); + return s; + } + + private void paintPercent(Event event, float count) { + Table table = (Table)event.widget; + int cell_width = table.getColumn(event.index).getWidth() - 1; + if (cell_width > 2) { + GC gc = event.gc; + float percent = count * 100 / sample_count; + int width = (int)(cell_width * percent / 100); + if (width > cell_width) width = cell_width; + if (width >= 2) { + Color bg = gc.getBackground(); + Color fg = gc.getForeground(); + gc.setBackground(getColor(new RGB(bg.getRed() / 3 + 170, bg.getGreen() / 3 + 170, bg.getBlue() / 3))); + gc.setForeground(getColor(new RGB(bg.getRed() / 3 + 170, bg.getGreen() / 3, bg.getBlue() / 3))); + gc.fillGradientRectangle(event.x, event.y, width, event.height, true); + gc.drawRectangle(new Rectangle(event.x, event.y, width - 1, event.height - 1)); + gc.setBackground(bg); + gc.setForeground(fg); + } + String text = toPercent(count); + Point size = event.gc.textExtent(text); + int offset = Math.max(0, (event.height - size.y) / 2); + gc.drawText(text, event.x + 2, event.y + offset, true); + } + } + private void selectionChanged(ISelection s) { if (s instanceof IStructuredSelection) { final Object obj = ((IStructuredSelection)s).getFirstElement(); @@ -1129,6 +1219,8 @@ public class ProfilerView extends ViewPart { if (params == null) { params = new HashMap<String,Object>(); params.put(IProfiler.PARAM_FRAME_CNT, FRAME_COUNT); + params.put(PARAM_AGGREGATE, Boolean.TRUE); + params.put(PARAM_STACK_TRACE, Boolean.FALSE); configuration.put(ctx, params); } params.put(PARAM_VIEW_UPDATE_PERIOD, node.getModel().getProfilerReadDelay()); @@ -1142,19 +1234,27 @@ public class ProfilerView extends ViewPart { private void stop(TCFNode node) { assert Protocol.isDispatchThread(); - Map<String,Object> params = new HashMap<String,Object>(); - configure(node, params); + configure(node, null); } private void configure(final TCFNode node, final Map<String,Object> params) { TCFModel model = node.getModel(); Map<String,Object> prf_cfg = model.getProfilerConfiguration(node.getID()); - Object frame_cnt = params.get(IProfiler.PARAM_FRAME_CNT); - if (frame_cnt != null) prf_cfg.put(IProfiler.PARAM_FRAME_CNT, frame_cnt); - else prf_cfg.remove(IProfiler.PARAM_FRAME_CNT); + if (params != null) { + Object frame_cnt = null; + Boolean stack_trace = (Boolean)params.get(PARAM_STACK_TRACE); + if (stack_trace != null && stack_trace.booleanValue()) { + frame_cnt = params.get(IProfiler.PARAM_FRAME_CNT); + } + if (frame_cnt == null) frame_cnt = Integer.valueOf(1); + prf_cfg.put(IProfiler.PARAM_FRAME_CNT, frame_cnt); + } + else { + prf_cfg.remove(IProfiler.PARAM_FRAME_CNT); + } model.sendProfilerConfiguration(node.getID()); ProfileModel prf_model = models.get(model); - if (frame_cnt == null) { + if (params == null) { ProfileData prf_data = null; if (prf_model != null) prf_data = prf_model.data.get(node.getID()); if (prf_data != null) prf_data.stopped = true; @@ -1266,6 +1366,7 @@ public class ProfilerView extends ViewPart { IWorkbenchWindow window = getSite().getWorkbenchWindow(); IDebugContextService dcs = DebugUITools.getDebugContextManager().getContextService(window); dcs.removeDebugContextListener(selection_listener); + disposeColors(); super.dispose(); } } |