From c2845a63b7bf74179d9a7b8207dbb8a68aa716d8 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Wed, 31 Aug 2016 16:27:11 -0400 Subject: [PATCH] timing: Bug 500592: fix symbols for with debug info of Lttng 2.8 The process ID of the trace application is propagated so that it can be used for the Function Duration Density view and Flame Graph view. For the Flame Graph it uses the the timestamp of the maximum segment to get the symbol name from the LTTng UST symbol provider. For the Function density view it takes the start time of the segment. Change-Id: Id3eb817f156e30b9be4996b732de05bc335418b9 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/80298 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- .../callgraph/AbstractCalledFunction.java | 9 ++- .../callgraph/AggregatedCalledFunction.java | 11 ++++ .../core/callgraph/CallGraphAnalysis.java | 55 ++++++++++++++----- .../timing/core/callgraph/CalledFunction.java | 6 +- .../core/callgraph/CalledFunctionFactory.java | 24 +++++--- .../core/callgraph/CalledStringFunction.java | 6 +- .../core/callgraph/ICalledFunction.java | 7 +++ .../timing/ui/callgraph/SymbolAspect.java | 9 +++ .../FlameGraphPresentationProvider.java | 9 +++ .../timing/ui/flamegraph/FlamegraphEvent.java | 11 ++++ 10 files changed, 119 insertions(+), 28 deletions(-) diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AbstractCalledFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AbstractCalledFunction.java index 0cf4b70392..a3138d0df0 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AbstractCalledFunction.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AbstractCalledFunction.java @@ -52,8 +52,9 @@ abstract class AbstractCalledFunction implements ICalledFunction { private final List fChildren = new ArrayList<>(); private final @Nullable ICalledFunction fParent; protected long fSelfTime = 0; + private final int fProcessId; - public AbstractCalledFunction(long start, long end, int depth, @Nullable ICalledFunction parent) { + public AbstractCalledFunction(long start, long end, int depth, int processId, @Nullable ICalledFunction parent) { if (start > end) { throw new IllegalArgumentException(Messages.TimeError + "[" + start + "," + end + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } @@ -63,6 +64,7 @@ abstract class AbstractCalledFunction implements ICalledFunction { fParent = parent; // It'll be modified once we add a child to it fSelfTime = fEnd - fStart; + fProcessId = processId; } @Override @@ -121,6 +123,11 @@ abstract class AbstractCalledFunction implements ICalledFunction { return fDepth; } + @Override + public int getProcessId() { + return fProcessId; + } + @Override public int compareTo(@Nullable ISegment o) { if (o == null) { diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java index 719f7e45fa..51f4f834a6 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java @@ -45,6 +45,7 @@ public class AggregatedCalledFunction { private final AggregatedCalledFunctionStatistics fStatistics; private long fDuration; private long fSelfTime; + private final int fProcessId; /** * Constructor, parent is not null @@ -60,6 +61,7 @@ public class AggregatedCalledFunction { fDuration = calledFunction.getLength(); fSelfTime = calledFunction.getLength(); fDepth = calledFunction.getDepth(); + fProcessId = calledFunction.getProcessId(); fMaxDepth = parent.getMaxDepth(); fParent = parent; fStatistics = new AggregatedCalledFunctionStatistics(calledFunction, calledFunction); @@ -78,6 +80,7 @@ public class AggregatedCalledFunction { fDuration = calledFunction.getLength(); fSelfTime = calledFunction.getLength(); fDepth = calledFunction.getDepth(); + fProcessId = calledFunction.getProcessId(); fMaxDepth = maxDepth; fParent = null; fStatistics = new AggregatedCalledFunctionStatistics(calledFunction, calledFunction); @@ -236,6 +239,14 @@ public class AggregatedCalledFunction { fSelfTime += selfTime; } + /** + * The process ID of the trace application. + * @return The process Id + */ + public int getProcessId() { + return fProcessId; + } + /** * Returns whether the function has callees. * diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CallGraphAnalysis.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CallGraphAnalysis.java index fab4c6a40c..e679508037 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CallGraphAnalysis.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CallGraphAnalysis.java @@ -180,8 +180,9 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem } List processQuarks = ss.getQuarks(processesPattern); for (int processQuark : processQuarks) { + int processId = getProcessId(ss, processQuark, ss.getCurrentEndTime()); for (int threadQuark : ss.getQuarks(processQuark, threadsPattern)) { - if (!iterateOverQuark(ss, threadQuark, callStackPath, monitor)) { + if (!iterateOverQuark(ss, processId, threadQuark, callStackPath, monitor)) { return false; } } @@ -196,20 +197,22 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem * * @param stateSystem * The state system - * @param quark - * The quark + * @param processId + * The process ID of the traced application + * @param threadQuark + * The thread quark * @param subAttributePath * sub-Attributes path * @param monitor * The monitor * @return Boolean */ - private boolean iterateOverQuark(ITmfStateSystem stateSystem, int quark, String[] subAttributePath, IProgressMonitor monitor) { - String threadName = stateSystem.getAttributeName(quark); + private boolean iterateOverQuark(ITmfStateSystem stateSystem, int processId, int threadQuark, String[] subAttributePath, IProgressMonitor monitor) { + String threadName = stateSystem.getAttributeName(threadQuark); long threadId = -1; ITmfStateInterval interval = null; try { - interval = stateSystem.querySingleState(stateSystem.getStartTime(), quark); + interval = stateSystem.querySingleState(stateSystem.getStartTime(), threadQuark); ITmfStateValue threadStateValue = interval.getStateValue(); if (threadStateValue.getType() == Type.LONG || threadStateValue.getType() == Type.INTEGER) { threadId = threadStateValue.unboxLong(); @@ -226,13 +229,13 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem try { long curTime = stateSystem.getStartTime(); long limit = stateSystem.getCurrentEndTime(); - AbstractCalledFunction initSegment = CalledFunctionFactory.create(0, 0, 0, threadName, null); + AbstractCalledFunction initSegment = CalledFunctionFactory.create(0, 0, 0, threadName, processId, null); ThreadNode init = new ThreadNode(initSegment, 0, threadId); while (curTime < limit) { if (monitor.isCanceled()) { return false; } - int callStackQuark = stateSystem.getQuarkRelative(quark, subAttributePath); + int callStackQuark = stateSystem.getQuarkRelative(threadQuark, subAttributePath); fCurrentQuarks = stateSystem.getSubAttributes(callStackQuark, false); if (fCurrentQuarks.isEmpty()) { return false; @@ -246,10 +249,10 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem long intervalStart = interval.getStartTime(); long intervalEnd = interval.getEndTime(); // Create the segment for the first call event. - AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, depth, stateValue, null); + AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, depth, stateValue, processId, null); fRootFunctions.add(segment); AggregatedCalledFunction firstNode = new AggregatedCalledFunction(segment, fCurrentQuarks.size()); - if (!findChildren(segment, depth, stateSystem, fCurrentQuarks.size() + fCurrentQuarks.get(depth), firstNode, monitor)) { + if (!findChildren(segment, depth, stateSystem, fCurrentQuarks.size() + fCurrentQuarks.get(depth), firstNode, processId, monitor)) { return false; } init.addChild(firstNode); @@ -278,13 +281,15 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem * The quark of the segment parent ss The actual state system * @param maxQuark * The last quark in the state system - * @param AggregatedCalledFunction + * @param aggregatedCalledFunction * A node in the aggregation tree + * @param processId + * The process ID of the traced application * @param monitor * The progress monitor The progress monitor TODO: if stack size * is an issue, convert to a stack instead of recursive function */ - private boolean findChildren(AbstractCalledFunction node, int depth, ITmfStateSystem ss, int maxQuark, AggregatedCalledFunction aggregatedCalledFunction, IProgressMonitor monitor) { + private boolean findChildren(AbstractCalledFunction node, int depth, ITmfStateSystem ss, int maxQuark, AggregatedCalledFunction aggregatedCalledFunction, int processId, IProgressMonitor monitor) { fStore.add(node); long curTime = node.getStart(); long limit = node.getEnd(); @@ -310,10 +315,10 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem if (intervalStart < node.getStart() || intervalEnd > limit) { return true; } - AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, node.getDepth() + 1, stateValue, node); + AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, node.getDepth() + 1, stateValue, processId, node); AggregatedCalledFunction childNode = new AggregatedCalledFunction(segment, aggregatedCalledFunction); // Search for the children with the next quark. - findChildren(segment, depth + 1, ss, maxQuark, childNode, monitor); + findChildren(segment, depth + 1, ss, maxQuark, childNode, processId, monitor); aggregatedCalledFunction.addChild(childNode); node.addChild(segment); } @@ -383,4 +388,26 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem return ImmutableList.copyOf(fThreadNodes); } + private static int getProcessId(ITmfStateSystem ss, int processQuark, long curTime) { + int processId = -1; + if (processQuark != ITmfStateSystem.ROOT_ATTRIBUTE) { + try { + ITmfStateInterval interval = ss.querySingleState(curTime, processQuark); + String processName = ss.getAttributeName(processQuark); + ITmfStateValue processStateValue = interval.getStateValue(); + if (processStateValue.getType() == Type.INTEGER) { + processId = processStateValue.unboxInt(); + } else { + try { + processId = Integer.parseInt(processName); + } catch (NumberFormatException e) { + /* use default processId */ + } + } + } catch (StateSystemDisposedException e) { + // ignore + } + } + return processId; + } } \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunction.java index 3764581bd9..b7417fb6c5 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunction.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunction.java @@ -39,11 +39,13 @@ public class CalledFunction extends AbstractCalledFunction { * The symbol of the call stack function * @param depth * The depth in the call stack of a function + * @param processId + * The process ID of the traced application * @param parent * The caller, can be null for root elements */ - protected CalledFunction(long start, long end, long symbol, int depth, @Nullable ICalledFunction parent) { - super(start, end, depth, parent); + protected CalledFunction(long start, long end, long symbol, int depth, int processId, @Nullable ICalledFunction parent) { + super(start, end, depth, processId, parent); fSymbol = symbol; } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunctionFactory.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunctionFactory.java index 26e93958bf..6f91b59a4b 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunctionFactory.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledFunctionFactory.java @@ -37,24 +37,26 @@ public class CalledFunctionFactory { * the depth * @param stateValue * the symbol + * @param processId + * The process ID of the traced application * @param parent * the parent node - * @return an ICalledFunction with the specified propertiess + * @return an ICalledFunction with the specified properties */ - public static AbstractCalledFunction create(long start, long end, int depth, ITmfStateValue stateValue, @Nullable ICalledFunction parent) { + public static AbstractCalledFunction create(long start, long end, int depth, ITmfStateValue stateValue, int processId, @Nullable ICalledFunction parent) { switch (stateValue.getType()) { case CUSTOM: throw new IllegalArgumentException(ERROR_MSG + stateValue.getType() + SEPARATOR + stateValue.toString()); case DOUBLE: throw new IllegalArgumentException(ERROR_MSG + stateValue.getType() + SEPARATOR + stateValue.toString()); case INTEGER: - return create(start, end, depth, stateValue.unboxInt(), parent); + return create(start, end, depth, stateValue.unboxInt(), processId, parent); case LONG: - return create(start, end, depth, stateValue.unboxLong(), parent); + return create(start, end, depth, stateValue.unboxLong(), processId, parent); case NULL: throw new IllegalArgumentException(ERROR_MSG + stateValue.getType() + SEPARATOR + stateValue.toString()); case STRING: - return create(start, end, depth, stateValue.unboxStr(), parent); + return create(start, end, depth, stateValue.unboxStr(), processId, parent); default: throw new IllegalArgumentException(ERROR_MSG + stateValue.getType() + SEPARATOR + stateValue.toString()); } @@ -72,15 +74,17 @@ public class CalledFunctionFactory { * the depth * @param value * the symbol + * @param processId + * The process ID of the traced application * @param parent * the parent node * @return an ICalledFunction with the specified propertiess */ - private static CalledFunction create(long start, long end, int depth, long value, @Nullable ICalledFunction parent) { + private static CalledFunction create(long start, long end, int depth, long value, int processId, @Nullable ICalledFunction parent) { if (start > end) { throw new IllegalArgumentException(Messages.TimeError + '[' + start + ',' + end + ']'); } - return new CalledFunction(start, end, value, depth, parent); + return new CalledFunction(start, end, value, depth, processId, parent); } /** @@ -95,14 +99,16 @@ public class CalledFunctionFactory { * the depth * @param value * the symbol + * @param processId + * The process ID of the traced application * @param parent * the parent node * @return an ICalledFunction with the specified properties */ - public static CalledStringFunction create(long start, long end, int depth, String value, @Nullable ICalledFunction parent) { + public static CalledStringFunction create(long start, long end, int depth, String value, int processId, @Nullable ICalledFunction parent) { if (start > end) { throw new IllegalArgumentException(Messages.TimeError + '[' + start + ',' + end + ']'); } - return new CalledStringFunction(start, end, value, depth, parent); + return new CalledStringFunction(start, end, value, depth, processId, parent); } } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledStringFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledStringFunction.java index d6ea018953..96756dba6a 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledStringFunction.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CalledStringFunction.java @@ -41,11 +41,13 @@ public class CalledStringFunction extends AbstractCalledFunction { * The symbol of the call stack function * @param depth * The depth in the call stack of a function + * @param processId + * The process ID of the traced application * @param parent * The caller, can be null for root elements */ - protected CalledStringFunction(long start, long end, String symbol, int depth, @Nullable ICalledFunction parent) { - super(start, end, depth, parent); + protected CalledStringFunction(long start, long end, String symbol, int depth, int processId, @Nullable ICalledFunction parent) { + super(start, end, depth, processId, parent); fSymbol = symbol; } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/ICalledFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/ICalledFunction.java index 5fb05ac0cc..e19a61fa64 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/ICalledFunction.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/ICalledFunction.java @@ -61,4 +61,11 @@ public interface ICalledFunction extends ISegment { */ int getDepth(); + /** + * The process ID of the traced application + * + * @return The process ID + */ + int getProcessId(); + } \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/callgraph/SymbolAspect.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/callgraph/SymbolAspect.java index 0ac537e0f8..0f7631d0ff 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/callgraph/SymbolAspect.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/callgraph/SymbolAspect.java @@ -79,6 +79,15 @@ public final class SymbolAspect implements ISegmentAspect { if (symbolText == null) { return "0x" + Long.toHexString(longAddress); //$NON-NLS-1$ } + // take the start time in the query for the symbol name + long time = segment.getStart(); + int pid = calledFunction.getProcessId(); + if (pid > 0) { + String text = provider.getSymbolText(pid, time, longAddress); + if (text != null) { + return text; + } + } return symbolText; } return String.valueOf(symbol); diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java index 70330e0888..8b70648c18 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java @@ -134,6 +134,15 @@ public class FlameGraphPresentationProvider extends TimeGraphPresentationProvide if (funcSymbol == null) { return "0x" + Long.toHexString(longAddress); //$NON-NLS-1$ } + // take time of max segment for time a query the symbol name + long time = event.getStatistics().getMaxSegment().getStart(); + int pid = event.getProcessId(); + if (pid > 0) { + String text = symbolProvider.getSymbolText(pid, time, longAddress); + if (text != null) { + return text; + } + } } else { return event.getSymbol().toString(); } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java index 59d52d20fc..c393f486b1 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java @@ -27,6 +27,7 @@ public class FlamegraphEvent extends TimeEvent { private final Object fSymbol; private final long fSelfTime; + private final int fProcessId; private final AggregatedCalledFunctionStatistics fStatistics; /** @@ -43,6 +44,7 @@ public class FlamegraphEvent extends TimeEvent { super(source, beginTime, aggregatedFunction.getDuration(), String.valueOf(aggregatedFunction.getSymbol()).hashCode() % MODULO + MODULO); fSymbol = aggregatedFunction.getSymbol(); fStatistics = aggregatedFunction.getFunctionStatistics(); + fProcessId = aggregatedFunction.getProcessId(); fSelfTime = aggregatedFunction.getSelfTime(); } @@ -72,4 +74,13 @@ public class FlamegraphEvent extends TimeEvent { public long getSelfTime() { return fSelfTime; } + + /** + * The process ID of the traced application + * + * @return process id + */ + public int getProcessId() { + return fProcessId; + } } -- 2.34.1