Skip to content

Commit

Permalink
OTF2: Add system architecture in callstack analysis
Browse files Browse the repository at this point in the history
Updated the OTF2 callstack analysis so it displays the system
architecture. Now the different processes can be grouped/expanded by
node and nodes can be grouped/expanded by cluster.

Test traces can be found here:
https://github.com/dorsal-lab/OTF2_testcases

Signed-off-by: yoann-heitz <yoann.heitz@polymtl.ca>
Change-Id: Ia621df1c7fdbe106cb67f79801670fc5c1d3d1ab
Reviewed-on: https://git.eclipse.org/r/c/tracecompass.incubator/org.eclipse.tracecompass.incubator/+/189315
Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Marco Miller <marco.miller@ericsson.com>
  • Loading branch information
yoann-heitz authored and MatthewKhouzam committed Mar 29, 2022
1 parent cc3de14 commit b48bf8e
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,13 @@ protected ArrayList<Long> getMembersFromCommunicatorReference(int communicatorRe
return members;
}

/**
* Getter for the fStringId field
*
* @return the fStringId field
*/
protected Map<Integer, String> getStringId() {
return fStringId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public interface IOtf2Fields {
*/
String OTF2_NAME = "name"; //$NON-NLS-1$

/**
* Class name field name
*/
String OTF2_CLASS_NAME = "className"; //$NON-NLS-1$

/**
* Communicator field name
*/
Expand Down Expand Up @@ -83,13 +88,23 @@ public interface IOtf2Fields {
*/
String OTF2_SELF = "self"; //$NON-NLS-1$

/**
* System tree parent field name
*/
String OTF2_SYSTEM_TREE_PARENT = "systemTreeParent"; //$NON-NLS-1$

/**
* Location field name
*/
String OTF2_LOCATION = "location"; //$NON-NLS-1$

/**
* LocationType field name
* Location group type field name
*/
String OTF2_LOCATION_GROUP_TYPE = "locationGroupType"; //$NON-NLS-1$

/**
* Location type field name
*/
String OTF2_LOCATION_TYPE = "locationType"; //$NON-NLS-1$

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
package org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.callstack;

import java.util.Map;
import java.util.Queue;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
Expand Down Expand Up @@ -52,6 +53,132 @@ public class Otf2CallStackStateProvider extends AbstractOtf2StateProvider {
*/
public static final String PROCESSES = "Processes"; //$NON-NLS-1$

/**
* Whitespace string
*/
public static final String WHITESPACE = " "; //$NON-NLS-1$

/**
* Long representing the maximum value for a 32-bits unsigned integer
*/
protected static final long MAX_UINT32 = (1L << 32) - 1;

/**
* A class representing a node from the system tree. It is used to represent
* how the different machines are distributed into a MPI cluster and how the
* MPI ranks are distributed on each node.
*
* @author Yoann Heitz
*
*/
private class SystemTreeNode {
private final long fParentId;
private final int fNameId;
private final int fClassNameId;
private int fSystemTreeNodeQuark;

public SystemTreeNode(long parentId, int nameId, int classNameId) {
fParentId = parentId;
fNameId = nameId;
fClassNameId = classNameId;
fSystemTreeNodeQuark = UNKNOWN_ID;
}

public String getFullName() {
Map<Integer, String> stringIds = getStringId();
String name = stringIds.get(fNameId);
String className = stringIds.get(fClassNameId);
return className + WHITESPACE + name;
}

/*
* The method used to initialize the quark associated to this node. If
* the node ID of the parent of this node is the maximum value for
* unsigned integer, then this node is the root of a system tree. Else,
* the parent node is usually a machine node. Its quark must be
* retrieved and initialized if it was not done before.
*/
public void initializeQuarks(ITmfStateSystemBuilder ssb) {
if (fParentId == MAX_UINT32) {
fSystemTreeNodeQuark = ssb.getQuarkAbsoluteAndAdd(PROCESSES, getFullName());
} else {
int machineQuark = getSystemTreeNodeQuark(fParentId);
if (machineQuark == UNKNOWN_ID) {
SystemTreeNode parentNode = fMapSystemTreeNode.get(fParentId);
if (parentNode == null) {
return;
}
parentNode.initializeQuarks(ssb);
machineQuark = getSystemTreeNodeQuark(fParentId);
}
if (machineQuark != UNKNOWN_ID) {
fSystemTreeNodeQuark = ssb.getQuarkRelativeAndAdd(machineQuark, getFullName());
}
}
}

public int getQuark() {
return fSystemTreeNodeQuark;
}
}

private int getSystemTreeNodeQuark(long systemTreeNodeId) {
SystemTreeNode systemTreeNode = fMapSystemTreeNode.get(systemTreeNodeId);
if (systemTreeNode == null) {
return UNKNOWN_ID;
}
return systemTreeNode.getQuark();
}

/**
* A class representing a location group. It is used to represent a MPI
* rank. The group is associated to a system tree node which is the node on
* which is running this MPI rank.
*
* @author Yoann Heitz
*
*/
private class LocationGroup {
private final long fParentId;
private final int fNameId;
private final int fType;
private int fLocationGroupQuark;

public LocationGroup(long parentId, int nameId, int type) {
fParentId = parentId;
fNameId = nameId;
fType = type;
fLocationGroupQuark = UNKNOWN_ID;
}

public String getFullName() {
String name = getStringId().get(fNameId);
if (fType == 1 && name != null) {
return name;
}
return UNKNOWN;
}

public void initializeQuarks(ITmfStateSystemBuilder ssb) {
int nodeQuark = getSystemTreeNodeQuark(fParentId);
if (nodeQuark != UNKNOWN_ID) {
fLocationGroupQuark = ssb.getQuarkRelativeAndAdd(nodeQuark, getFullName());
}
}

public int getQuark() {
return fLocationGroupQuark;
}
}

private int getLocationGroupQuark(int locationGroupId) {
LocationGroup locationGroup = fMapLocationGroup.get(locationGroupId);
if (locationGroup == null) {
return UNKNOWN_ID;
}
return locationGroup.getQuark();
}

/**
* A class representing a location. When an OTF2 event is encountered,
* methods from this class will be used to modify the state of the
Expand Down Expand Up @@ -80,20 +207,15 @@ public Location(long id, int nameId, int processId) {

/*
* This method will be called by each location when all definitions have
* been read : the names of the location and of the parent process may
* be computed at this moment, and the corresponding quarks may be
* created.
* been read : the name of the location may be computed at this moment,
* and the corresponding quark may be created.
*/
public void initializeQuarks(ITmfStateSystemBuilder ssb) {
// Get the names of the location and its parent process
// Get the name of the location
String locationName = getStringFromStringId(fLocationNameId);
Integer processStringId = fLocationGroupStringId.get(fProcessId);
if (processStringId == null) {
processStringId = UNKNOWN_ID;
}
String processName = getStringFromStringId(processStringId);
// Create the associated quarks
int processQuark = ssb.getQuarkAbsoluteAndAdd(PROCESSES, processName);

// Create the associated quark
int processQuark = getLocationGroupQuark(fProcessId);
fLocationQuark = ssb.getQuarkRelativeAndAdd(processQuark, locationName);
fCallStackQuark = ssb.getQuarkRelativeAndAdd(fLocationQuark, InstrumentedCallStackAnalysis.CALL_STACK);
}
Expand Down Expand Up @@ -299,11 +421,12 @@ public void mpiAllToRoot(ITmfEvent srcEvent, ITmfStateSystemBuilder ssb) {
/**
* Mapping tables required for this analysis
*/
private final Map<Integer, Integer> fLocationGroupStringId;
private final Map<Long, Location> fMapLocation;
private final Map<MessageIdentifiers, ITmfEvent> fMsgDataEvent;
private final LinkedList<RootToAllIdentifiers> fRootToAllQueue;
private final LinkedList<AllToRootIdentifiers> fAllToRootQueue;
private final Map<Long, SystemTreeNode> fMapSystemTreeNode = new HashMap<>();
private final Map<Integer, LocationGroup> fMapLocationGroup = new HashMap<>();
private final Map<Long, Location> fMapLocation = new HashMap<>();
private final Map<MessageIdentifiers, ITmfEvent> fMsgDataEvent = new HashMap<>();
private final Queue<RootToAllIdentifiers> fRootToAllQueue = new LinkedList<>();
private final Queue<AllToRootIdentifiers> fAllToRootQueue = new LinkedList<>();
private boolean fAllDefinitionsRead;

/**
Expand All @@ -312,17 +435,12 @@ public void mpiAllToRoot(ITmfEvent srcEvent, ITmfStateSystemBuilder ssb) {
*/
public Otf2CallStackStateProvider(@Nullable ITmfTrace trace) {
super(trace, ID);
fLocationGroupStringId = new HashMap<>();
fMsgDataEvent = new HashMap<>();
fMapLocation = new HashMap<>();
fRootToAllQueue = new LinkedList<>();
fAllToRootQueue = new LinkedList<>();
fAllDefinitionsRead = false;
}

@Override
public int getVersion() {
return 1;
return 2;
}

@Override
Expand Down Expand Up @@ -361,6 +479,10 @@ protected void processGlobalDefinition(ITmfEvent event, String name) {
processGroupMemberDefinition(event);
break;
}
case IOtf2GlobalDefinitions.OTF2_SYSTEM_TREE_NODE: {
processSystemTreeNodeDefinition(event);
break;
}
default:
return;
}
Expand All @@ -380,11 +502,27 @@ private void processLocationDefinition(ITmfEvent event) {
private void processLocationGroupDefinition(ITmfEvent event) {
ITmfEventField content = event.getContent();
Integer locationGroupReference = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_SELF);
Integer stringReference = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_NAME);
if (locationGroupReference == null || stringReference == null) {
Integer nameReference = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_NAME);
Integer locationGroupType = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_LOCATION_GROUP_TYPE);
Long parentReference = content.getFieldValue(Long.class, IOtf2Fields.OTF2_SYSTEM_TREE_PARENT);
if (locationGroupReference == null || nameReference == null || locationGroupType == null || parentReference == null) {
return;
}
fLocationGroupStringId.put(locationGroupReference, stringReference);
LocationGroup locationGroup = new LocationGroup(parentReference, nameReference, locationGroupType);
fMapLocationGroup.put(locationGroupReference, locationGroup);
}

private void processSystemTreeNodeDefinition(ITmfEvent event) {
ITmfEventField content = event.getContent();
Long selfReference = content.getFieldValue(Long.class, IOtf2Fields.OTF2_SELF);
Integer nameReference = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_NAME);
Integer classNameReference = content.getFieldValue(Integer.class, IOtf2Fields.OTF2_CLASS_NAME);
Long parentReference = content.getFieldValue(Long.class, IOtf2Fields.OTF2_SYSTEM_TREE_PARENT);
if (selfReference == null || nameReference == null || classNameReference == null || parentReference == null) {
return;
}
SystemTreeNode systemTreeNode = new SystemTreeNode(parentReference, nameReference, classNameReference);
fMapSystemTreeNode.put(selfReference, systemTreeNode);
}

@Override
Expand Down Expand Up @@ -441,6 +579,12 @@ protected void processOtf2Event(ITmfEvent event, String name, ITmfStateSystemBui
* Iterates over all the location and initializes the associated quarks
*/
private void initializeQuarks(ITmfStateSystemBuilder ssb) {
for (SystemTreeNode systemTreeNode : fMapSystemTreeNode.values()) {
systemTreeNode.initializeQuarks(ssb);
}
for (LocationGroup locationGroup : fMapLocationGroup.values()) {
locationGroup.initializeQuarks(ssb);
}
for (Location location : fMapLocation.values()) {
location.initializeQuarks(ssb);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.CallStackSeries;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.CallStackSeries.IThreadIdResolver;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.CallStackStateProvider;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.InstrumentedCallStackAnalysis;
import org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.AbstractOtf2Analysis;
import org.eclipse.tracecompass.incubator.internal.otf2.core.analysis.IOtf2Constants;
Expand All @@ -23,6 +28,8 @@
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;

import com.google.common.collect.ImmutableList;

/**
* OTF2 callstack analysis
*
Expand All @@ -32,12 +39,18 @@
public class Otf2CallstackAnalysis extends InstrumentedCallStackAnalysis {

private static final String ID_SUFFIX = ".callstack"; //$NON-NLS-1$
private static final int THREAD_DEPTH = 3;

@Override
public String getId() {
return AbstractOtf2Analysis.getAnalysisIdFromSuffix(ID_SUFFIX);
}

@Override
protected @NonNull IThreadIdResolver getCallStackTidResolver() {
return new CallStackSeries.AttributeValueThreadResolver(THREAD_DEPTH);
}

@Override
protected ITmfStateProvider createStateProvider() {
ITmfTrace trace = Objects.requireNonNull(getTrace());
Expand All @@ -59,4 +72,18 @@ protected Collection<Integer> getEdgeQuarks() {
}
return ss.getSubAttributes(edgeQuark, false);
}

/**
* Get the patterns for the clusters, nodes, processes and threads
*
* @return The patterns for the different levels in the state system
*/
@Override
protected List<String[]> getPatterns() {
return ImmutableList.of(
new String[] { CallStackStateProvider.PROCESSES, "*" }, //$NON-NLS-1$
new String[] { "*" }, //$NON-NLS-1$
new String[] { "*" }, //$NON-NLS-1$
new String[] { "*" }); //$NON-NLS-1$
}
}

0 comments on commit b48bf8e

Please sign in to comment.