Skip to content

Commit

Permalink
OTF2: Add an XY view to the flows analysis
Browse files Browse the repository at this point in the history
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
yoann-heitz authored and marco-miller committed Oct 17, 2022
1 parent ce99299 commit 333ec17
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,11 @@
id="org.eclipse.tracecompass.incubator.otf2.core.analysis.flows.dataprovider">
</dataProviderFactory>
</extension>
<extension
point="org.eclipse.tracecompass.tmf.core.dataprovider">
<dataProviderFactory
class="org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.flows.Otf2FlowsXYDataProviderFactory"
id="org.eclipse.tracecompass.incubator.otf2.core.analysis.flows.xy.dataprovider">
</dataProviderFactory>
</extension>
</plugin>
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
*
* @author Yoann Heitz
*/

@SuppressWarnings("restriction")
public class Otf2FlowsDataProvider extends AbstractTimeGraphDataProvider<Otf2FlowsAnalysis, TimeGraphEntryModel> implements IOutputStyleProvider {

Expand Down
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;
}
}
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ otf2.communicators = MPI communicators state
otf2.view.communicators = MPI communicators state
otf2.view.summarytimeline = Summary Timeline
otf2.view.flows = Flows
otf2.view.flows.xy = Flows (XY chart)
otf2.perspective = OTF2
20 changes: 19 additions & 1 deletion tracetypes/org.eclipse.tracecompass.incubator.otf2.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@
name="%otf2.view.flows"
restorable="true">
</view>
<view
category="org.eclipse.tracecompass.incubator.internal.otf2.ui.views.category"
class="org.eclipse.tracecompass.incubator.internal.otf2.ui.views.flows.Otf2FlowsXYView"
id="org.eclipse.tracecompass.incubator.otf2.ui.views.flows.xy"
icon="icons/otf2-icon.png"
name="%otf2.view.flows.xy"
restorable="true">
</view>
</extension>
<extension
point="org.eclipse.linuxtools.tmf.ui.tracetypeui">
Expand Down Expand Up @@ -86,4 +94,14 @@
</analysisModuleClass>
</output>
</extension>
</plugin>
<extension
point="org.eclipse.linuxtools.tmf.core.analysis">
<output
class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
id="org.eclipse.tracecompass.incubator.otf2.ui.views.flows.xy">
<analysisModuleClass
class="org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.flows.Otf2FlowsAnalysis">
</analysisModuleClass>
</output>
</extension>
</plugin>
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));
}
}
Loading

0 comments on commit 333ec17

Please sign in to comment.