blob: a04bc3f28ac5c5d5cf793a19e08915b4a19552a0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dimitrios Kolovos - initial API and implementation
******************************************************************************/
package org.eclipse.epsilon.profiling.dt;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.eclipse.epsilon.common.dt.util.EclipseUtil;
import org.eclipse.epsilon.common.module.ModuleElement;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.erl.execute.control.RuleProfiler;
import org.eclipse.epsilon.profiling.IProfilerListener;
import org.eclipse.epsilon.profiling.Profiler;
import org.eclipse.epsilon.profiling.ProfilerTarget;
import org.eclipse.epsilon.profiling.ProfilerTargetSummary;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
public class ProfilerView extends ViewPart implements IProfilerListener{
protected static final int ORDER_COLUMN = 0;
protected static final int TARGET_COLUMN = 1;
protected static final int TIMES_COLUMN = 2;
protected static final int CPU_COLUMN = 3;
protected static final int AVG_COLUMN = 4;
private TableViewer targetsViewer;
private TableViewer rulesViewer;
private TreeViewer detailsViewer;
protected OverviewViewer overviewViewer;
private CTabFolder folder;
protected boolean autoRefresh = false;
protected Image running = Activator.getImageDescriptor("icons/running.gif").createImage();
protected Image completed = Activator.getImageDescriptor("icons/completed.gif").createImage();
protected boolean sortChildrenTargetsByTime = false;
protected boolean showAggregatedWork = true;
protected List<ProfilerTargetSummary> targetSummaries = new ArrayList<>();
protected List<ProfilerTarget> rootTargets = new ArrayList<>();
class DetailsViewerContentProvider implements ITreeContentProvider {
@Override
public Object[] getElements(Object inputElement) {
return rootTargets.toArray();
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// TODO Auto-generated method stub
}
@Override
public Object[] getChildren(Object parentElement) {
List<ProfilerTarget> children = ((ProfilerTarget) parentElement).getChildren();
if (sortChildrenTargetsByTime) {
List<ProfilerTarget> temp = children;
children = new ArrayList<>();
children.addAll(temp);
Collections.sort(children, (o1, o2) -> {
if (o1.getWorked(showAggregatedWork) > o2.getWorked(showAggregatedWork)) {
return -1;
}
else if (o2.getWorked(showAggregatedWork) > o1.getWorked(showAggregatedWork)) {
return 1;
}
else {
return 0;
}
});
}
return children.toArray();
}
@Override
public Object getParent(Object element) {
return ((ProfilerTarget) element).getParent();
}
@Override
public boolean hasChildren(Object element) {
return ((ProfilerTarget) element).getChildren().size() > 0;
}
}
class DetailsViewerLabelProvider extends LabelProvider implements ITableLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0) {
return completed;
}
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
ProfilerTarget target = ((ProfilerTarget) element);
if (columnIndex == 0) return target.getName();
else if (columnIndex == 1) return target.getWorked(showAggregatedWork) + "";
else if (columnIndex == 2) return target.getData();
else {
ModuleElement moduleElement = target.getModuleElement();
if (moduleElement != null && moduleElement.getFile() != null) {
String label = moduleElement.getFile().getName();
if (moduleElement.getRegion() != null) {
label = label + " (" + moduleElement.getRegion().getStart().getLine() + ", " + moduleElement.getRegion().getStart().getColumn() + ")";
}
return label;
}
return "";
}
}
}
class ViewerLabelProvider extends LabelProvider implements ITableLabelProvider {
@Override
public Image getColumnImage(Object obj, int index) {
Image image = null;
if (index == ORDER_COLUMN) {
if (Profiler.INSTANCE.isRunning(obj.toString())) {
image = running;
}
else {
image = completed;
}
}
return image;
}
@Override
public Image getImage(Object obj) {
return PlatformUI.getWorkbench().
getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);
}
@Override
public String getColumnText(Object element, int columnIndex) {
return Objects.toString(element);
}
}
class RulesViewerLabelProvider extends ViewerLabelProvider {
@Override
public String getColumnText(Object element, int index) {
@SuppressWarnings("unchecked")
Map.Entry<?, Duration> entry = (Map.Entry<?, Duration>) element;
if (index == 0) {
return entry.getKey().toString();
}
return ""+entry.getValue().toMillis();//BenchmarkUtils.formatDuration(entry.getValue());
}
}
class TargetsViewerLabelProvider extends ViewerLabelProvider {
@Override
public String getColumnText(Object obj, int index) {
ProfilerTargetSummary summary = (ProfilerTargetSummary) obj;
switch (index) {
case ORDER_COLUMN:
//return Profiler.INSTANCE.getTargetNames().indexOf(obj.toString()) + "";
return summary.getIndex() + "";
case TARGET_COLUMN:
//return obj.toString();
return summary.getName();
case CPU_COLUMN:
//long cpuTime = Profiler.INSTANCE.getTotalTime(obj.toString(), showAggregatedWork);
//return cpuTime + "";
return showAggregatedWork ? summary.getExecutionTime().getAggregate() + "" : summary.getExecutionTime().getIndividual() + "";
case TIMES_COLUMN:
//long numberOfTimes = Profiler.INSTANCE.getExecutionCount(obj.toString());
//return "" + numberOfTimes;
return summary.getExecutionCount() + "";
case AVG_COLUMN:
long executionTime = showAggregatedWork ? summary.getExecutionTime().getAggregate() : summary.getExecutionTime().getIndividual();
//long numberOfTimes = Profiler.INSTANCE.getExecutionCount(obj.toString());
//long cpuTime = Profiler.INSTANCE.getTotalTime(obj.toString(), showAggregatedWork);
return "" + ((double)executionTime) / summary.getExecutionCount() ;
default:
return ""; //CollectionUtil.toString(Profiler.INSTANCE.getTargetHistory(obj.toString()));
}
}
}
/**
* The constructor.
*/
public ProfilerView() {
Profiler.INSTANCE.addListener(this);
}
/**
* This is a callback that will allow us
* to create the viewer and initialize it.
*/
@Override
public void createPartControl(Composite parent) {
folder = new CTabFolder(parent, SWT.NONE);
folder.setSimple(true);
folder.setTabPosition(SWT.BOTTOM);
CTabItem overviewItem = new CTabItem(folder,SWT.NONE);
overviewItem.setText("Summary");
overviewViewer = new OverviewViewer(folder, SWT.NONE);
overviewItem.setControl(overviewViewer);
CTabItem targetsViewerItem = new CTabItem(folder,SWT.NONE);
targetsViewerItem.setText("Targets");
CTabItem detailsViewerItem = new CTabItem(folder,SWT.NONE);
detailsViewerItem.setText("Details");
createTargetsTable();
createDetailsTree();
targetsViewerItem.setControl(targetsViewer.getControl());
//detailsViewerItem.setControl(new PlotComposite(folder,SWT.NONE));
detailsViewerItem.setControl(detailsViewer.getControl());
CTabItem rulesViewerItem = new CTabItem(folder,SWT.NONE);
rulesViewerItem.setText("Rules");
createRulesTable();
rulesViewerItem.setControl(rulesViewer.getControl());
folder.setSelection(overviewItem);
//hookContextMenu();
contributeToActionBars();
}
protected void createDetailsTree() {
detailsViewer = new TreeViewer(folder, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
detailsViewer.setContentProvider(new DetailsViewerContentProvider());
detailsViewer.setLabelProvider(new DetailsViewerLabelProvider());
detailsViewer.setInput(Profiler.INSTANCE.getRoot());
TreeColumn c = new TreeColumn(detailsViewer.getTree(), SWT.FULL_SELECTION);
c.setText("Target");
c.setWidth(150);
c = new TreeColumn(detailsViewer.getTree(), SWT.FULL_SELECTION);
c.setText("Execution Time");
c.setWidth(150);
c = new TreeColumn(detailsViewer.getTree(), SWT.FULL_SELECTION);
c.setText("Data");
c.setWidth(150);
c = new TreeColumn(detailsViewer.getTree(), SWT.FULL_SELECTION);
c.setText("Location");
c.setWidth(150);
detailsViewer.getTree().addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) {
ProfilerTarget target = (ProfilerTarget) ((IStructuredSelection) detailsViewer.getSelection()).getFirstElement();
if (target != null) {
ModuleElement moduleElement = target.getModuleElement();
if (moduleElement != null) {
EclipseUtil.openEditorAt(moduleElement);
}
}
}
@Override
public void mouseDown(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseUp(MouseEvent e) {
// TODO Auto-generated method stub
}
});
detailsViewer.getTree().setHeaderVisible(true);
detailsViewer.getTree().setLinesVisible(true);
}
protected void createTargetsTable() {
targetsViewer = new TableViewer(folder, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
targetsViewer.setContentProvider(new IStructuredContentProvider() {
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object parent) {
return targetSummaries.toArray();
}
});
targetsViewer.setLabelProvider(new TargetsViewerLabelProvider());
//targetsViewer.setSorter(new ProfilerTargetSorter());
targetsViewer.setInput(getViewSite());
TableColumn column = new LongTableColumn(targetsViewer, SWT.FULL_SELECTION);
column.setText(""); // Order column
column.setWidth(20);
column = new StringTableColumn(targetsViewer, SWT.FULL_SELECTION);
column.setText("Target");
column.setWidth(300);
column = new LongTableColumn(targetsViewer, SWT.FULL_SELECTION);
column.setText("# Times Executed");
column.setWidth(135);
column = new LongTableColumn(targetsViewer, SWT.FULL_SELECTION);
column.setText("Total Execution Time");
column.setWidth(195);
column = new DoubleTableColumn(targetsViewer, SWT.FULL_SELECTION);
column.setText("Average Execution Time");
column.setWidth(195);
targetsViewer.getTable().setHeaderVisible(true);
targetsViewer.getTable().setLinesVisible(true);
}
protected void createRulesTable() {
rulesViewer = new TableViewer(folder, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
rulesViewer.setContentProvider(new IStructuredContentProvider() {
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object parent) {
IEolContext context = Profiler.INSTANCE.getContext();
if (context == null) return new Object[0];
return ((RuleProfiler) context.getExecutorFactory().getExecutionController())
.getExecutionTimes().entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.toArray();
}
});
rulesViewer.setLabelProvider(new RulesViewerLabelProvider());
rulesViewer.setInput(getViewSite());
TableColumn column;
column = new StringTableColumn(rulesViewer, SWT.FULL_SELECTION);
column.setText("Rule Name");
column.setWidth(400);
column = new LongTableColumn(rulesViewer, SWT.FULL_SELECTION);
column.setText("Total CPU Time (ms)");
column.setWidth(250);
rulesViewer.getTable().setHeaderVisible(true);
//rulesViewer.getTable().setLinesVisible(true);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(new RefreshProfilerViewAction(this));
manager.add(new ToggleSortChildrenTargetsAction(this));
manager.add(new ToggleShowAggregatedWorkAction(this));
manager.add(new ToggleAutoRefreshAction(this));
manager.add(new ResetProfilerAction(this));
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
targetsViewer.getControl().setFocus();
}
@Override
public void targetStarted(String task) {
if (autoRefresh) refresh();
}
@Override
public void targetStopped(String task) {
if (autoRefresh) refresh();
}
@Override
public void refresh() {
targetSummaries = Profiler.INSTANCE.getTargetSummaries();
rootTargets = Profiler.INSTANCE.getRoot().getChildren();
Display.getDefault().asyncExec(() -> {
// TODO: why is total not used?
long total = 0;
for (ProfilerTargetSummary summary : targetSummaries) {
total += summary.getExecutionTime().getAggregate();
}
overviewViewer.setProfilerOverview(Profiler.INSTANCE.getOverview());
if (targetsViewer != null) {
targetsViewer.refresh();
}
if (detailsViewer != null) {
detailsViewer.refresh();
}
if (rulesViewer != null) {
rulesViewer.refresh();
}
});
}
public boolean isAutoRefresh() {
return autoRefresh;
}
public void setAutoRefresh(boolean autoRefresh) {
this.autoRefresh = autoRefresh;
}
public TableViewer getViewer() {
return targetsViewer;
}
public boolean isSortChildrenTargetsByTime() {
return sortChildrenTargetsByTime;
}
public void setSortChildrenTargetsByTime(boolean sortChildrenTargetsByTime) {
this.sortChildrenTargetsByTime = sortChildrenTargetsByTime;
}
public boolean isShowAggregatedWork() {
return showAggregatedWork;
}
public void setShowAggregatedWork(boolean showAggregatedWork) {
this.showAggregatedWork = showAggregatedWork;
}
}