diff options
4 files changed, 355 insertions, 77 deletions
diff --git a/docs/TCF Getting Started.html b/docs/TCF Getting Started.html index 8bbc66f25..e5772aa35 100644 --- a/docs/TCF Getting Started.html +++ b/docs/TCF Getting Started.html @@ -43,12 +43,12 @@ below are steps to create and populate Eclipse workspace with TCF projects:</p> <li><b>RSE (Remote System Explorer) SDK 3.3</b> or later, last tested with 3.3.1, recommended 3.3.1<br> <a href='http://download.eclipse.org/tm/downloads/'>http://download.eclipse.org/tm/downloads/</a> </ul> - <li><b>Optional</b> dependencies for Target Explorer: + <li><b>Optional</b> dependencies for Target Explorer: <ul> <li><b>RXTX (Java library to access serial ports)</b><br> - <a href='http://rxtx.qbang.org/eclipse/'>Eclipse update site at http://rxtx.qbang.org/eclipse/</a><br> - <a href='http://rxtx.qbang.org/eclipse/downloads/'>Download location at http://rxtx.qbang.org/eclipse/downloads/</a> - </ul> + <a href='http://rxtx.qbang.org/eclipse/'>Eclipse update site at http://rxtx.qbang.org/eclipse/</a><br> + <a href='http://rxtx.qbang.org/eclipse/downloads/'>Download location at http://rxtx.qbang.org/eclipse/downloads/</a> + </ul> <li>Clone TCF Java code from <a href='http://git.eclipse.org/c/tcf/org.eclipse.tcf.git'>Eclipse GIT repository</a>, using one of the following commands: <pre> git clone git://git.eclipse.org/gitroot/tcf/org.eclipse.tcf.git diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java index 998a0439b..ed7924e86 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java @@ -58,6 +58,7 @@ public class ImageCache { IMG_SIGNALS = "icons/signals.gif", IMG_MEMORY_MAP = "icons/memory-map.gif", + IMG_PROFILER = "icons/profiler.png", IMG_ARRAY_PARTITION = "icons/full/obj16/arraypartition_obj.gif", 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 new file mode 100644 index 000000000..1d5c09d08 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/profiler/ProfilerSettingsDlg.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2013 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.profiler; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.services.IProfiler; + +class ProfilerSettingsDlg extends Dialog { + + static final String PARAM_VIEW_UPDATE_PERIOD = "ViewUpdatePeriod"; + static final String PARAM_AGGREGATE = "Aggregate"; + + Map<String,Object> conf; + Map<String,Object> data; + + private Button aggregate_button; + private Button stack_trace_button; + private Text frame_cnt_text; + private Text view_update_text; + + protected ProfilerSettingsDlg(Shell shell, Map<String,Object> conf) { + super(shell); + this.conf = conf; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Profiler Configuration"); + shell.setImage(ImageCache.getImage(ImageCache.IMG_PROFILER)); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + updateButtons(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + createFields(composite); + setData(); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + aggregate_button = new Button(composite, SWT.CHECK); + aggregate_button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL, 0, true, false, 2, 1)); + aggregate_button.setFont(font); + aggregate_button.setText("Aggregate per function"); + + stack_trace_button = new Button(composite, SWT.CHECK); + stack_trace_button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL, 0, true, false, 2, 1)); + stack_trace_button.setFont(font); + stack_trace_button.setText("Enable stack tracing"); + + stack_trace_button.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + updateButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateButtons(); + } + }); + + Label frame_cnt_label = new Label(composite, SWT.WRAP); + frame_cnt_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + frame_cnt_label.setFont(font); + frame_cnt_label.setText("Max stack frames count:"); + + frame_cnt_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + frame_cnt_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + frame_cnt_text.setFont(font); + + frame_cnt_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + Label view_update_label = new Label(composite, SWT.WRAP); + view_update_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + view_update_label.setFont(font); + view_update_label.setText("View update interval (sec):"); + + view_update_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + view_update_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + view_update_text.setFont(font); + + view_update_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + } + + private void updateButtons() { + Button btn = getButton(IDialogConstants.OK_ID); + if (btn != null) btn.setEnabled(true); + frame_cnt_text.setEnabled(stack_trace_button.getSelection()); + } + + 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()); + } + + 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_VIEW_UPDATE_PERIOD, new Integer(view_update_text.getText())); + } + + @Override + protected void okPressed() { + try { + getData(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Invalid data"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + return; + } + super.okPressed(); + } +} 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 76a972ac8..bf0b515b8 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 @@ -34,6 +34,7 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; @@ -75,6 +76,7 @@ import org.eclipse.tcf.services.ILineNumbers; import org.eclipse.tcf.services.IProfiler; import org.eclipse.tcf.services.ISymbols; import org.eclipse.tcf.util.TCFDataCache; +import org.eclipse.tcf.util.TCFTask; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.part.ViewPart; @@ -83,6 +85,8 @@ public class ProfilerView extends ViewPart { private static final long UPDATE_DELAY = 4000; private static final int FRAME_COUNT = 5; + private static final String PARAM_VIEW_UPDATE_PERIOD = ProfilerSettingsDlg.PARAM_VIEW_UPDATE_PERIOD; + private static final String PARAM_AGGREGATE = ProfilerSettingsDlg.PARAM_AGGREGATE; private static class ProfileSample { int cnt; @@ -95,6 +99,7 @@ public class ProfilerView extends ViewPart { private static class ProfileData { final String ctx; + final Map<String,Object> params; boolean stopped; boolean unsupported; @@ -110,8 +115,11 @@ public class ProfilerView extends ViewPart { ProfileEntry[] entries; @SuppressWarnings("unchecked") - ProfileData(String ctx, int frame_cnt) { + 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(); map = new Map[frame_cnt]; for (int i = 0; i < frame_cnt; i++) { map[i] = new HashMap<BigInteger,List<ProfileSample>>(); @@ -121,6 +129,7 @@ public class ProfilerView extends ViewPart { private static class ProfileEntry { final BigInteger addr; + final Set<BigInteger> addr_list = new HashSet<BigInteger>(); String name; String file_full; @@ -131,6 +140,7 @@ public class ProfilerView extends ViewPart { ProfileEntry[] up; ProfileEntry[] dw; + boolean src_info_valid; boolean mark; ProfileEntry(BigInteger addr) { @@ -264,12 +274,15 @@ public class ProfilerView extends ViewPart { final int sorting; final TCFNode selection; final Map<BigInteger,ProfileEntry> entries = new HashMap<BigInteger,ProfileEntry>(); - final Map<BigInteger,String> funcs = new HashMap<BigInteger,String>(); + final Map<BigInteger,BigInteger> addr_to_func_addr = new HashMap<BigInteger,BigInteger>(); + final Map<BigInteger,String> addr_to_func_id = new HashMap<BigInteger,String>(); final TCFNodeExecContext node; final ProfileData prof_data; final ISymbols symbols; final ILineNumbers line_numbers; + final boolean aggrerate; final int generation; + TCFDataCache<?> pending; boolean done; Update() { @@ -287,34 +300,71 @@ public class ProfilerView extends ViewPart { symbols = null; line_numbers = null; generation = 0; + aggrerate = false; } else { node = (TCFNodeExecContext)selection; symbols = node.getChannel().getRemoteService(ISymbols.class); line_numbers = node.getChannel().getRemoteService(ILineNumbers.class); generation = p.generation_inp; + Boolean b = (Boolean)p.params.get(PARAM_AGGREGATE); + aggrerate = b != null && b.booleanValue(); } last_update = this; } - private boolean getFuncName(ProfileEntry pe) { - if (symbols == null) return true; - String func_id = funcs.get(pe.addr); + private String getFuncID(BigInteger addr) { + if (symbols == null) return ""; + String func_id = addr_to_func_id.get(addr); if (func_id == null) { func_id = ""; - TCFDataCache<TCFFunctionRef> func_cache = node.getFuncInfo(pe.addr); + TCFDataCache<TCFFunctionRef> func_cache = node.getFuncInfo(addr); if (func_cache != null) { - if (!func_cache.validate(this)) return false; + if (!func_cache.validate()) { + pending = func_cache; + return null; + } TCFFunctionRef func_data = func_cache.getData(); if (func_data != null && func_data.symbol_id != null) { func_id = func_data.symbol_id; } } - funcs.put(pe.addr, func_id); + addr_to_func_id.put(addr, func_id); + } + return func_id; + } + + private BigInteger getFuncAddress(BigInteger addr) { + if (!aggrerate) return addr; + BigInteger func_addr = addr_to_func_addr.get(addr); + if (func_addr != null) return func_addr; + String func_id = getFuncID(addr); + if (func_id == null) return null; + func_addr = addr; + if (func_id.length() > 0) { + TCFDataCache<ISymbols.Symbol> sym_cache = node.getModel().getSymbolInfoCache(func_id); + if (!sym_cache.validate()) { + pending = sym_cache; + return null; + } + ISymbols.Symbol sym_data = sym_cache.getData(); + if (sym_data != null && sym_data.getAddress() != null) { + func_addr = JSON.toBigInteger(sym_data.getAddress()); + } } + addr_to_func_addr.put(addr, func_addr); + return func_addr; + } + + private boolean getFuncName(ProfileEntry pe) { + String func_id = getFuncID(pe.addr); + if (func_id == null) return false; if (func_id.length() > 0) { TCFDataCache<ISymbols.Symbol> sym_cache = node.getModel().getSymbolInfoCache(func_id); - if (!sym_cache.validate(this)) return false; + if (!sym_cache.validate()) { + pending = sym_cache; + return false; + } ISymbols.Symbol sym_data = sym_cache.getData(); if (sym_data != null && sym_data.getName() != null) { pe.name = sym_data.getName(); @@ -327,7 +377,10 @@ public class ProfilerView extends ViewPart { if (line_numbers == null) return true; TCFDataCache<TCFSourceRef> line_cache = node.getLineInfo(pe.addr); if (line_cache == null) return true; - if (!line_cache.validate(this)) return false; + if (!line_cache.validate()) { + pending = line_cache; + return false; + } TCFSourceRef line_data = line_cache.getData(); if (line_data != null && line_data.area != null) { pe.file_full = TCFSourceLookupParticipant.toFileName(line_data.area); @@ -343,29 +396,31 @@ public class ProfilerView extends ViewPart { return true; } - void linkEntry(ProfileEntry pe) { + private void linkEntry(ProfileEntry pe) { Set<ProfileEntry> set_up = new HashSet<ProfileEntry>(); Set<ProfileEntry> set_dw = new HashSet<ProfileEntry>(); for (int n = 0; n < prof_data.map.length; n++) { - List<ProfileSample> s0 = prof_data.map[n].get(pe.addr); - if (s0 != null) { - for (ProfileSample x : s0) { - assert x.trace[n].equals(pe.addr); - if (x.trace.length <= n + 1) continue; - BigInteger addr_up = x.trace[n + 1]; - ProfileEntry pe_up = entries.get(addr_up); - set_up.add(pe_up); + for (BigInteger addr : pe.addr_list) { + List<ProfileSample> s0 = prof_data.map[n].get(addr); + if (s0 != null) { + for (ProfileSample x : s0) { + assert addr.equals(x.trace[n]); + if (x.trace.length <= n + 1) continue; + BigInteger addr_up = getFuncAddress(x.trace[n + 1]); + ProfileEntry pe_up = entries.get(addr_up); + set_up.add(pe_up); + } } - } - if (n == prof_data.map.length - 1) continue; - List<ProfileSample> s1 = prof_data.map[n + 1].get(pe.addr); - if (s1 != null) { - for (ProfileSample x : s1) { - assert x.trace.length > n + 1; - assert x.trace[n + 1].equals(pe.addr); - BigInteger addr_dw = x.trace[n]; - ProfileEntry pe_dw = entries.get(addr_dw); - set_dw.add(pe_dw); + if (n == prof_data.map.length - 1) continue; + List<ProfileSample> s1 = prof_data.map[n + 1].get(addr); + if (s1 != null) { + for (ProfileSample x : s1) { + assert x.trace.length > n + 1; + assert addr.equals(x.trace[n + 1]); + BigInteger addr_dw = getFuncAddress(x.trace[n]); + ProfileEntry pe_dw = entries.get(addr_dw); + set_dw.add(pe_dw); + } } } } @@ -373,7 +428,7 @@ public class ProfilerView extends ViewPart { if (set_dw.size() > 0) pe.dw = set_dw.toArray(new ProfileEntry[set_dw.size()]); } - void addUpTotal(ProfileEntry pe, float cnt) { + private void addUpTotal(ProfileEntry pe, float cnt) { if (cnt <= 0.1 || pe.up == null) return; pe.mark = true; int n = 0; @@ -393,6 +448,7 @@ public class ProfilerView extends ViewPart { @Override public void run() { + pending = null; if (done) return; if (last_update != this) return; if (prof_data != null && generation != prof_data.generation_out) { @@ -402,29 +458,39 @@ public class ProfilerView extends ViewPart { else { for (int n = 0; n < prof_data.map.length; n++) { for (BigInteger addr : prof_data.map[n].keySet()) { - ProfileEntry pe = entries.get(addr); - if (pe != null) continue; - pe = new ProfileEntry(addr); - if (!getFuncName(pe)) return; - if (!getLineInfo(pe)) return; - if (n == 0) { - List<ProfileSample> s = prof_data.map[0].get(addr); - for (ProfileSample x : s) pe.count += x.cnt; + BigInteger func_addr = getFuncAddress(addr); + if (func_addr == null) continue; + ProfileEntry pe = entries.get(func_addr); + if (pe == null) { + pe = new ProfileEntry(func_addr); + entries.put(pe.addr, pe); + } + if (!pe.addr_list.contains(addr)) { + if (n == 0) { + List<ProfileSample> s = prof_data.map[0].get(addr); + for (ProfileSample x : s) pe.count += x.cnt; + } + pe.addr_list.add(addr); + } + if (!pe.src_info_valid) { + pe.src_info_valid = true; + if (!getFuncName(pe)) pe.src_info_valid = false; + if (!getLineInfo(pe)) pe.src_info_valid = false; } - entries.put(pe.addr, pe); } } - for (ProfileEntry pe : entries.values()) { - linkEntry(pe); + if (pending != null) { + pending.wait(this); + return; } + for (ProfileEntry pe : entries.values()) linkEntry(pe); for (List<ProfileSample> lps : prof_data.map[0].values()) { for (ProfileSample ps : lps) { int n = 0; while (n < ps.trace.length) { - ProfileEntry pe = entries.get(ps.trace[n]); - if (n == ps.trace.length - 1) { - addUpTotal(pe, ps.cnt); - } + BigInteger func_addr = getFuncAddress(ps.trace[n]); + ProfileEntry pe = entries.get(func_addr); + if (n == ps.trace.length - 1) addUpTotal(pe, ps.cnt); pe.total += ps.cnt; n++; } @@ -435,10 +501,12 @@ public class ProfilerView extends ViewPart { if (pe.dw != null) Arrays.sort(pe.dw, new SampleComparator(2)); } } - ProfileEntry[] arr = entries.values().toArray(new ProfileEntry[entries.size()]); - Arrays.sort(arr, new SampleComparator(sorting)); prof_data.generation_out = generation; - prof_data.entries = arr; + prof_data.entries = entries.values().toArray(new ProfileEntry[entries.size()]); + assert pending == null; + } + if (prof_data != null && prof_data.entries != null) { + Arrays.sort(prof_data.entries, new SampleComparator(sorting)); } done = true; final boolean enable_start = @@ -454,26 +522,25 @@ public class ProfilerView extends ViewPart { parent.getDisplay().asyncExec(new Runnable() { @Override public void run() { + if (parent.isDisposed()) return; action_start.setEnabled(enable_start); action_stop.setEnabled(enable_stop); profile_node = node; Object viewer_input = prof_data != null ? prof_data.entries : null; - if (viewer_main.getInput() != viewer_input) { - ISelection s = viewer_main.getSelection(); - ProfilerView.this.sample_count = sample_count; - viewer_main.setInput(viewer_input); - if (s instanceof IStructuredSelection) { - IStructuredSelection ss = (IStructuredSelection)s; - List<ProfileEntry> l = new ArrayList<ProfileEntry>(); - for (Object obj : ss.toArray()) { - if (obj instanceof ProfileEntry) { - ProfileEntry pe = (ProfileEntry)obj; - pe = entries.get(pe.addr); - if (pe != null) l.add(pe); - } + ISelection s = viewer_main.getSelection(); + ProfilerView.this.sample_count = sample_count; + viewer_main.setInput(viewer_input); + if (s instanceof IStructuredSelection) { + IStructuredSelection ss = (IStructuredSelection)s; + List<ProfileEntry> l = new ArrayList<ProfileEntry>(); + for (Object obj : ss.toArray()) { + if (obj instanceof ProfileEntry) { + ProfileEntry pe = (ProfileEntry)obj; + pe = entries.get(pe.addr); + if (pe != null) l.add(pe); } - setSelection(l, false); } + setSelection(l, false); } if (!enable_start) { status.setText("Selected context does not support profiling"); @@ -550,13 +617,26 @@ public class ProfilerView extends ViewPart { private final Action action_start = new Action("Start", ImageCache.getImageDescriptor(ImageCache.IMG_THREAD_RUNNNIG)) { @Override public void run() { - Protocol.invokeLater(new Runnable() { + final TCFNode node = selection; + if (node == null) return; + Map<String,Object> conf = new TCFTask<Map<String,Object>>() { @Override public void run() { - if (selection == null) return; - start(selection); + done(getConfiguration(node.getID())); } - }); + }.getE(); + ProfilerSettingsDlg dlg = new ProfilerSettingsDlg(getSite().getShell(), conf); + if (dlg.open() == Window.OK) { + final Map<String,Object> params = dlg.data; + Protocol.invokeLater(new Runnable() { + @Override + public void run() { + configuration.put(node.getID(), params); + if (selection != node) return; + start(selection); + } + }); + } } }; @@ -605,6 +685,9 @@ public class ProfilerView extends ViewPart { 60 }; + private final Map<String,Map<String,Object>> configuration = + new HashMap<String,Map<String,Object>>(); + @Override public void createPartControl(Composite parent) { this.parent = parent; @@ -944,18 +1027,27 @@ public class ProfilerView extends ViewPart { viewer_main.getControl().setFocus(); } - public void start(TCFNode node) { + private Map<String,Object> getConfiguration(String ctx) { + Map<String,Object> params = configuration.get(ctx); + if (params == null) { + params = new HashMap<String,Object>(); + params.put(IProfiler.PARAM_FRAME_CNT, FRAME_COUNT); + params.put(PARAM_VIEW_UPDATE_PERIOD, 4); + configuration.put(ctx, params); + } + return params; + } + + private void start(TCFNode node) { assert Protocol.isDispatchThread(); if (!launch_listener_ok) { TCFModelManager.getModelManager().addListener(launch_listener); launch_listener_ok = true; } - Map<String,Object> params = new HashMap<String,Object>(); - params.put(IProfiler.PARAM_FRAME_CNT, FRAME_COUNT); - configure(node, params); + configure(node, getConfiguration(node.getID())); } - public void stop(TCFNode node) { + private void stop(TCFNode node) { assert Protocol.isDispatchThread(); Map<String,Object> params = new HashMap<String,Object>(); configure(node, params); @@ -975,8 +1067,7 @@ public class ProfilerView extends ViewPart { if (d != null) d.stopped = true; } else { - Number n = (Number)params.get(IProfiler.PARAM_FRAME_CNT); - ProfileData d = new ProfileData(node.getID(), n.intValue()); + ProfileData d = new ProfileData(node.getID(), params); if (m == null) data.put(node.getModel(), m = new HashMap<String,ProfileData>()); m.put(d.ctx, d); } @@ -1044,6 +1135,7 @@ public class ProfilerView extends ViewPart { } private void addSample(ProfileData p, BigInteger[] trace, int len, int cnt) { + assert len > 0; p.sample_count += cnt; p.generation_inp++; ProfileSample ps = null; |