private StackSourceFrameIndex GetSourceLocation(CallTreeNodeBase node, string cellText, out Dictionary <StackSourceFrameIndex, float> retVal) { var m = Regex.Match(cellText, "<<(.*!.*)>>"); if (m.Success) { cellText = m.Groups[1].Value; } var frameIndexCounts = new Dictionary <StackSourceFrameIndex, float>(); node.GetSamples(false, sampleIdx => { var matchingFrameIndex = StackSourceFrameIndex.Invalid; var sample = this.callTree.StackSource.GetSampleByIndex(sampleIdx); var callStackIdx = sample.StackIndex; while (callStackIdx != StackSourceCallStackIndex.Invalid) { var frameIndex = this.callTree.StackSource.GetFrameIndex(callStackIdx); var frameName = this.callTree.StackSource.GetFrameName(frameIndex, false); if (frameName == cellText) { matchingFrameIndex = frameIndex; } callStackIdx = this.callTree.StackSource.GetCallerIndex(callStackIdx); } if (matchingFrameIndex != StackSourceFrameIndex.Invalid) { frameIndexCounts.TryGetValue(matchingFrameIndex, out float count); frameIndexCounts[matchingFrameIndex] = count + sample.Metric; } return(true); }); var maxFrameIdx = StackSourceFrameIndex.Invalid; float maxFrameIdxCount = -1; foreach (var keyValue in frameIndexCounts) { if (keyValue.Value >= maxFrameIdxCount) { maxFrameIdxCount = keyValue.Value; maxFrameIdx = keyValue.Key; } } retVal = frameIndexCounts; return(maxFrameIdx); }
private SourceLocation GetSourceLocation(CallTreeNodeBase asCallTreeNodeBase, string cellText, out SortedDictionary <int, float> metricOnLine) { metricOnLine = null; var m = Regex.Match(cellText, "<<(.*!.*)>>"); if (m.Success) { cellText = m.Groups[1].Value; } var frameIndexCounts = new Dictionary <StackSourceFrameIndex, float>(); asCallTreeNodeBase.GetSamples(false, delegate(StackSourceSampleIndex sampleIdx) { var matchingFrameIndex = StackSourceFrameIndex.Invalid; var sample = this.stacksource.GetSampleByIndex(sampleIdx); var callStackIdx = sample.StackIndex; while (callStackIdx != StackSourceCallStackIndex.Invalid) { var frameIndex = this.stacksource.GetFrameIndex(callStackIdx); var frameName = this.stacksource.GetFrameName(frameIndex, false); if (frameName == cellText) { matchingFrameIndex = frameIndex; // We keep overwriting it, so we get the entry closest to the root. } callStackIdx = this.stacksource.GetCallerIndex(callStackIdx); } if (matchingFrameIndex != StackSourceFrameIndex.Invalid) { float count = 0; frameIndexCounts.TryGetValue(matchingFrameIndex, out count); frameIndexCounts[matchingFrameIndex] = count + sample.Metric; } return(true); }); var maxFrameIdx = StackSourceFrameIndex.Invalid; float maxFrameIdxCount = -1; foreach (var keyValue in frameIndexCounts) { if (keyValue.Value >= maxFrameIdxCount) { maxFrameIdxCount = keyValue.Value; maxFrameIdx = keyValue.Key; } } if (maxFrameIdx == StackSourceFrameIndex.Invalid) { return(null); } // Find the most primitive TraceEventStackSource TraceEventStackSource asTraceEventStackSource = GetTraceEventStackSource(this.stacksource); if (asTraceEventStackSource == null) { return(null); } var frameToLine = new Dictionary <StackSourceFrameIndex, int>(); var sourceLocation = asTraceEventStackSource.GetSourceLine(maxFrameIdx, this.reader); if (sourceLocation != null) { var filePathForMax = sourceLocation.SourceFile.BuildTimeFilePath; metricOnLine = new SortedDictionary <int, float>(); // Accumulate the counts on a line basis foreach (StackSourceFrameIndex frameIdx in frameIndexCounts.Keys) { var loc = asTraceEventStackSource.GetSourceLine(frameIdx, this.reader); if (loc != null && loc.SourceFile.BuildTimeFilePath == filePathForMax) { frameToLine[frameIdx] = loc.LineNumber; float metric; metricOnLine.TryGetValue(loc.LineNumber, out metric); metric += frameIndexCounts[frameIdx]; metricOnLine[loc.LineNumber] = metric; } } } bool commonMethodIdxSet = false; MethodIndex commonMethodIdx = MethodIndex.Invalid; var nativeAddressFreq = new SortedDictionary <ulong, Tuple <int, float> >(); foreach (var keyValue in frameIndexCounts) { var codeAddr = asTraceEventStackSource.GetFrameCodeAddress(keyValue.Key); if (codeAddr != CodeAddressIndex.Invalid) { var methodIdx = asTraceEventStackSource.TraceLog.CodeAddresses.MethodIndex(codeAddr); if (methodIdx != MethodIndex.Invalid) { if (!commonMethodIdxSet) { commonMethodIdx = methodIdx; // First time, set it as the common method. } else if (methodIdx != commonMethodIdx) { methodIdx = MethodIndex.Invalid; // More than one method, give up. } commonMethodIdxSet = true; } var nativeAddr = asTraceEventStackSource.TraceLog.CodeAddresses.Address(codeAddr); var lineNum = 0; frameToLine.TryGetValue(keyValue.Key, out lineNum); nativeAddressFreq[nativeAddr] = new Tuple <int, float>(lineNum, keyValue.Value); } } foreach (var keyValue in nativeAddressFreq) { Console.WriteLine(" {0,12:x} : {1,6} {2,10:f1}", keyValue.Key, keyValue.Value.Item1, keyValue.Value.Item2); } if (sourceLocation == null) { return(null); } foreach (var keyVal in metricOnLine) { Console.WriteLine(" Line {0,5}: Metric {1,5:n1}", keyVal.Key, keyVal.Value); } return(sourceLocation); }