-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OTF2: Add an XY view to the flows analysis
Added an XY view similar to the one already present in the flows analysis. This view allows to have more precise information about the input and output flows of the different threads, processes, nodes and clusters, while the previous timeline view allows to understand more globally the behavior of the traced application. When selecting several leafs in the tree viewer, the sum of the flows values of these leafs (and then of the intermediary nodes) is then displayed for the parents. It allows for example to compare the flows of several processes among one node. Signed-off-by: yoann-heitz <yoann.heitz@polymtl.ca> Change-Id: Ifa148ab6b124e7e0a736b8038d3a109abfeddc8c Reviewed-on: https://git.eclipse.org/r/c/tracecompass.incubator/org.eclipse.tracecompass.incubator/+/192556 Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org> Tested-by: Marco Miller <marco.miller@ericsson.com> Reviewed-by: Marco Miller <marco.miller@ericsson.com>
- Loading branch information
1 parent
ce99299
commit 333ec17
Showing
8 changed files
with
377 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
...pse/tracecompass/incubator/internal/otf2/core/analysis/flows/Otf2FlowsXYDataProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2022 École Polytechnique de Montréal | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License 2.0 which | ||
* accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
**********************************************************************/ | ||
|
||
package org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.flows; | ||
|
||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
|
||
import org.eclipse.core.runtime.IProgressMonitor; | ||
import org.eclipse.jdt.annotation.Nullable; | ||
import org.eclipse.tracecompass.incubator.internal.otf2.core.Activator; | ||
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | ||
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | ||
import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | ||
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | ||
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils; | ||
import org.eclipse.tracecompass.tmf.core.dataprovider.DataType; | ||
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage; | ||
import org.eclipse.tracecompass.tmf.core.model.IOutputStyleProvider; | ||
import org.eclipse.tracecompass.tmf.core.model.OutputStyleModel; | ||
import org.eclipse.tracecompass.tmf.core.model.YModel; | ||
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphEntryModel; | ||
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeDataModel; | ||
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel; | ||
import org.eclipse.tracecompass.tmf.core.model.xy.AbstractTreeCommonXDataProvider; | ||
import org.eclipse.tracecompass.tmf.core.model.xy.IYModel; | ||
import org.eclipse.tracecompass.tmf.core.model.xy.TmfXYAxisDescription; | ||
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse; | ||
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; | ||
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableList.Builder; | ||
|
||
/** | ||
* Abstract data provider for the OTF2 flows XY view. | ||
* | ||
* @author Yoann Heitz | ||
*/ | ||
public class Otf2FlowsXYDataProvider extends AbstractTreeCommonXDataProvider<Otf2FlowsAnalysis, TmfTreeDataModel> implements IOutputStyleProvider { | ||
|
||
/** Data provider suffix ID */ | ||
private static final String SUFFIX = ".xy.dataprovider"; //$NON-NLS-1$ | ||
|
||
private static final String TITLE = "Flows XY dataprovider"; //$NON-NLS-1$ | ||
|
||
/** Y axis description for this data provider */ | ||
private static final TmfXYAxisDescription Y_AXIS_DESCRIPTION = new TmfXYAxisDescription("Perceived data flows", "B/s", DataType.NUMBER); //$NON-NLS-1$ //$NON-NLS-2$ | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param trace | ||
* the trace for this provider | ||
* @param analysisModule | ||
* the corresponding analysis module | ||
*/ | ||
public Otf2FlowsXYDataProvider(ITmfTrace trace, Otf2FlowsAnalysis analysisModule) { | ||
super(trace, analysisModule); | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return getAnalysisModule().getId() + SUFFIX; | ||
} | ||
|
||
@Override | ||
public TmfModelResponse<OutputStyleModel> fetchStyle(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) { | ||
return new TmfModelResponse<>(null, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); | ||
} | ||
|
||
@Override | ||
protected @Nullable Collection<IYModel> getYSeriesModels(ITmfStateSystem ss, Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) throws StateSystemDisposedException { | ||
ImmutableList.Builder<IYModel> ySeries = ImmutableList.builder(); | ||
Map<Integer, double[]> quarkToValues = new HashMap<>(); | ||
|
||
// Prepare the quarks to display | ||
Collection<Long> selectedItems = DataProviderParameterUtils.extractSelectedItems(fetchParameters); | ||
if (selectedItems == null) { | ||
return null; | ||
} | ||
|
||
List<Long> times = DataProviderParameterUtils.extractTimeRequested(fetchParameters); | ||
if (times == null) { | ||
return null; | ||
} | ||
|
||
Map<Long, Integer> idsToQuarks = getSelectedEntries(selectedItems); | ||
for (Integer quark : idsToQuarks.values()) { | ||
quarkToValues.put(quark, new double[times.size()]); | ||
} | ||
|
||
// Query the state system to fill the arrays of values | ||
try { | ||
for (ITmfStateInterval interval : ss.query2D(quarkToValues.keySet(), times)) { | ||
if (monitor != null && monitor.isCanceled()) { | ||
return null; | ||
} | ||
double[] row = quarkToValues.get(interval.getAttribute()); | ||
Object value = interval.getValue(); | ||
if (row != null && (value instanceof Number)) { | ||
Double dblValue = ((Number) value).doubleValue(); | ||
for (int i = 0; i < times.size(); i++) { | ||
Long time = times.get(i); | ||
if (interval.getStartTime() <= time && interval.getEndTime() >= time) { | ||
// Convert from B/ns to B/s and fill the array | ||
double valueInBPerSecond = dblValue * 1E9; | ||
row[i] = valueInBPerSecond; | ||
|
||
// Increment parents values | ||
int parentQuark = ss.getParentAttributeQuark(interval.getAttribute()); | ||
while (parentQuark != ITmfStateSystem.ROOT_ATTRIBUTE) { | ||
double[] parentRow = quarkToValues.get(parentQuark); | ||
if (parentRow != null) { | ||
parentRow[i] += valueInBPerSecond; | ||
} | ||
parentQuark = ss.getParentAttributeQuark(parentQuark); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} catch (IndexOutOfBoundsException | TimeRangeException | StateSystemDisposedException e) { | ||
Activator.getInstance().logError(e.getMessage()); | ||
return null; | ||
} | ||
|
||
for (Entry<Integer, double[]> values : quarkToValues.entrySet()) { | ||
ySeries.add(new YModel(getId(values.getKey()), ss.getFullAttributePath(values.getKey()), values.getValue(), Y_AXIS_DESCRIPTION)); | ||
} | ||
return ySeries.build(); | ||
} | ||
|
||
@Override | ||
protected boolean isCacheable() { | ||
return false; | ||
} | ||
|
||
@Override | ||
protected TmfTreeModel<TmfTreeDataModel> getTree(ITmfStateSystem ss, Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) throws StateSystemDisposedException { | ||
Builder<TmfTreeDataModel> builder = new Builder<>(); | ||
long parentId = getId(ITmfStateSystem.ROOT_ATTRIBUTE); | ||
builder.add(new TmfTreeDataModel(parentId, -1, String.valueOf(getTrace().getName()))); | ||
addChildren(ss, builder, ITmfStateSystem.ROOT_ATTRIBUTE, parentId); | ||
return new TmfTreeModel<>(Collections.emptyList(), builder.build()); | ||
} | ||
|
||
/** | ||
* Add children to the TmfTreeModel | ||
* | ||
* @param ss | ||
* the state system | ||
* @param builder | ||
* builder for TmfTreeDataModel | ||
* @param quark | ||
* the quark for which the children will be added | ||
* @param parentId | ||
* the ID of the parent quark | ||
*/ | ||
protected void addChildren(ITmfStateSystem ss, Builder<TmfTreeDataModel> builder, int quark, long parentId) { | ||
for (Integer child : ss.getSubAttributes(quark, false)) { | ||
long childId = getId(child); | ||
String name = ss.getFullAttributePath(child); | ||
builder.add(new TimeGraphEntryModel(childId, parentId, name, ss.getStartTime(), ss.getCurrentEndTime(), true)); | ||
addChildren(ss, builder, child, childId); | ||
} | ||
} | ||
|
||
@Override | ||
protected String getTitle() { | ||
return TITLE; | ||
} | ||
|
||
/** | ||
* Gets the ID of this data provider | ||
* | ||
* @return the ID of this data provider | ||
*/ | ||
public static String getFullDataProviderId() { | ||
return Otf2FlowsAnalysis.getFullAnalysisId() + SUFFIX; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
...cecompass/incubator/internal/otf2/core/analysis/flows/Otf2FlowsXYDataProviderFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2022 École Polytechnique de Montréal | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License 2.0 which | ||
* accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
**********************************************************************/ | ||
|
||
package org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.flows; | ||
|
||
import org.eclipse.jdt.annotation.Nullable; | ||
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; | ||
import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; | ||
import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; | ||
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | ||
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | ||
|
||
/** | ||
* Factory for the flows XY data provider | ||
* | ||
* @author Yoann Heitz | ||
*/ | ||
public class Otf2FlowsXYDataProviderFactory implements IDataProviderFactory { | ||
|
||
@Override | ||
public @Nullable ITmfTreeDataProvider<? extends ITmfTreeDataModel> createProvider(ITmfTrace trace) { | ||
Otf2FlowsAnalysis module = TmfTraceUtils.getAnalysisModuleOfClass(trace, Otf2FlowsAnalysis.class, Otf2FlowsAnalysis.getFullAnalysisId()); | ||
if (module != null) { | ||
module.schedule(); | ||
return new Otf2FlowsXYDataProvider(trace, module); | ||
} | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
.../src/org/eclipse/tracecompass/incubator/internal/otf2/ui/views/flows/Otf2FlowsXYView.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2022 École Polytechnique de Montréal | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License 2.0 which | ||
* accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
**********************************************************************/ | ||
|
||
package org.eclipse.tracecompass.incubator.internal.otf2.ui.views.flows; | ||
|
||
import java.util.Comparator; | ||
import java.util.Objects; | ||
|
||
import org.eclipse.jdt.annotation.NonNull; | ||
import org.eclipse.jdt.annotation.Nullable; | ||
import org.eclipse.swt.widgets.Composite; | ||
import org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.flows.Otf2FlowsXYDataProvider; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractSelectTreeViewer2; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.xychart.TmfXYChartViewer; | ||
import org.eclipse.tracecompass.tmf.ui.viewers.xychart.linechart.TmfXYChartSettings; | ||
import org.eclipse.tracecompass.tmf.ui.views.xychart.TmfChartView; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
|
||
/** | ||
* XY View for OTF2 flows | ||
* | ||
* @author Yoann Heitz | ||
*/ | ||
public class Otf2FlowsXYView extends TmfChartView { | ||
|
||
/** View ID suffix */ | ||
public static final String ID_SUFFIX = "flows.xy"; //$NON-NLS-1$ | ||
|
||
/** Name of this view **/ | ||
private static final String VIEW_NAME = "Flows (XY view)"; //$NON-NLS-1$ | ||
|
||
/** Chart settings for this view **/ | ||
private static final TmfXYChartSettings SETTINGS = new TmfXYChartSettings("Perceived data flows", "Time", "Perceived data flows", 1); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | ||
|
||
/** | ||
* Constructor | ||
*/ | ||
public Otf2FlowsXYView() { | ||
super(VIEW_NAME); | ||
} | ||
|
||
@Override | ||
protected TmfXYChartViewer createChartViewer(Composite parent) { | ||
return new Otf2FlowsXYViewer(parent, SETTINGS, Otf2FlowsXYDataProvider.getFullDataProviderId()); | ||
} | ||
|
||
private static final class TreeXyViewer extends AbstractSelectTreeViewer2 { | ||
|
||
public TreeXyViewer(Composite parent) { | ||
super(parent, 1, Otf2FlowsXYDataProvider.getFullDataProviderId()); | ||
} | ||
|
||
@Override | ||
protected ITmfTreeColumnDataProvider getColumnDataProvider() { | ||
return () -> ImmutableList.of(createColumn("Nodes", Comparator.comparing(TmfTreeViewerEntry::getName)), //$NON-NLS-1$ | ||
new TmfTreeColumnData("Legend")); //$NON-NLS-1$ | ||
} | ||
} | ||
|
||
@Override | ||
protected @NonNull TmfViewer createLeftChildViewer(@Nullable Composite parent) { | ||
return new TreeXyViewer(Objects.requireNonNull(parent)); | ||
} | ||
} |
Oops, something went wrong.