internal void BuildAllocationTrace(Graph graph, int stackTraceIndex, int typeIndex, ulong size, Vertex[] typeVertex, Vertex[] funcVertex, ref Vertex[] vertexStack) { int stackPtr = BuildVertexStack(stackTraceIndex, funcVertex, ref vertexStack, 2); Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if ((typeVertex[typeIndex].interestLevel & InterestLevel.Interesting) == InterestLevel.Interesting && ReadNewLog.InterestingCallStack(vertexStack, stackPtr)) { vertexStack[stackPtr] = typeVertex[typeIndex]; stackPtr++; stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } fromVertex = toVertex; toVertex = graph.BottomVertex; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } }
internal Graph(object graphSource) { this.graphSource = graphSource; vertices = new Dictionary<string, Vertex>(); topVertex = FindOrCreateVertex("<root>", null, null); bottomVertex = FindOrCreateVertex("<bottom>", null, null); }
/*public void GetCallGraph(ReadLogResult readLogResult) { callGraph = readLogResult.callstackHistogram.BuildCallGraph(); PlaceVertices(); } public void GetFunctionGraph(ReadLogResult readLogResult) { graph = readLogResult.functionList.BuildFunctionGraph(); PlaceVertices(); }*/ public int SelectedVertexCount(out Vertex selectedVertex) { int selectedCount = 0; selectedVertex = null; foreach (Vertex v in graph.vertices.Values) { if (v.selected) { selectedCount++; selectedVertex = v; } } return selectedCount; }
internal int BuildVertexStack(int stackTraceIndex, Vertex[] funcVertex, ref Vertex[] vertexStack, int skipCount) { int[] stackTrace = readNewLog.stacktraceTable.IndexToStacktrace(stackTraceIndex); while (vertexStack.Length < stackTrace.Length + 3) { vertexStack = new Vertex[vertexStack.Length * 2]; } for (int i = skipCount; i < stackTrace.Length; i++) { vertexStack[i - skipCount] = funcVertex[stackTrace[i]]; } return stackTrace.Length - skipCount; }
internal static int FilterVertices(Vertex[] vertexStack, int stackPtr) { bool display = false; for (int i = 0; i < stackPtr; i++) { Vertex vertex = vertexStack[i]; switch (vertex.interestLevel & InterestLevel.InterestingChildren) { case InterestLevel.Ignore: if (display) vertex.interestLevel |= InterestLevel.Display; break; case InterestLevel.InterestingChildren: display = true; break; default: display = false; break; } } display = false; for (int i = stackPtr - 1; i >= 0; i--) { Vertex vertex = vertexStack[i]; switch (vertex.interestLevel & InterestLevel.InterestingParents) { case InterestLevel.Ignore: if (display) vertex.interestLevel |= InterestLevel.Display; break; case InterestLevel.InterestingParents: display = true; break; default: display = false; break; } } int newStackPtr = 0; for (int i = 0; i < stackPtr; i++) { Vertex vertex = vertexStack[i]; if ((vertex.interestLevel & (InterestLevel.Display | InterestLevel.Interesting)) != InterestLevel.Ignore) { vertexStack[newStackPtr++] = vertex; vertex.interestLevel &= ~InterestLevel.Display; } } return newStackPtr; }
internal static bool InterestingCallStack(Vertex[] vertexStack, int stackPtr) { if ((vertexStack[stackPtr - 1].interestLevel & InterestLevel.Interesting) == InterestLevel.Interesting) return true; for (int i = stackPtr - 2; i >= 0; i--) { switch (vertexStack[i].interestLevel & InterestLevel.InterestingChildren) { case InterestLevel.Ignore: break; case InterestLevel.InterestingChildren: return true; default: return false; } } return false; }
static bool RepeatedElementsPresent(Vertex[] path, int length) { for (int i = 0; i < length; i++) { Vertex element = path[i]; int hint = element.hint; if (hint < i && path[hint] == element) return true; element.hint = i; } return false; }
void BuildFuncVertices(Graph graph, ref Vertex[] funcVertex) { for (int i = 0; i < readNewLog.funcName.Length; i++) { string name = readNewLog.funcName[i]; string signature = readNewLog.funcSignature[i]; if (name != null && signature != null) readNewLog.AddFunctionVertex(i, name, signature, graph, ref funcVertex); } }
internal Edge(Vertex fromVertex, Vertex toVertex) { this.fromVertex = fromVertex; this.toVertex = toVertex; this.weight = 0; }
internal static int SqueezeOutRepetitions(Vertex[] path, int length) { if (!RepeatedElementsPresent(path, length)) return length; int k = 0; int l = 0; while (l < length) { int repetitionLength = LargestRepetition(path, k, l, length); if (repetitionLength == 0) path[k++] = path[l++]; else l += repetitionLength; } if (RepeatedElementsPresent(path, k)) { int[] level = new int[k]; for (int i = 0; i < k; i++) { level[i] = 0; Vertex element = path[i]; int hint = element.hint; if (hint < i && path[hint] == element) level[i] = level[hint] + 1; element.hint = i; } for (int i = 0; i < k; i++) { if (level[i] != 0) { Vertex v = path[i]; string newName = v.name + "(" + level[i] + ")"; path[i] = path[i].containingGraph.FindOrCreateVertex(newName, v.signature, v.moduleName); } } } return k; }
internal Graph BuildHandleAllocationGraph() { Vertex[] funcVertex = new Vertex[1]; Vertex[] vertexStack = new Vertex[1]; Graph graph = new Graph(this); graph.graphType = Graph.GraphType.HandleAllocationGraph; BuildFuncVertices(graph, ref funcVertex); for (int i = 0; i < typeSizeStacktraceToCount.Length; i++) { if (typeSizeStacktraceToCount[i] > 0) { int[] stacktrace = readNewLog.stacktraceTable.IndexToStacktrace(i); uint count = (uint)typeSizeStacktraceToCount[i]; BuildHandleAllocationTrace(graph, i, count, funcVertex, ref vertexStack); } } foreach (Vertex v in graph.vertices.Values) v.active = true; graph.BottomVertex.active = false; return graph; }
internal void BuildTypeVertices(Graph graph, ref Vertex[] typeVertex) { for (int i = 0; i < readNewLog.typeName.Length; i++) { string typeName = readNewLog.typeName[i]; if (typeName == null) typeName = string.Format("???? type {0}", i); readNewLog.AddTypeVertex(i, typeName, graph, ref typeVertex); } }
internal Graph BuildClassGraph() { Vertex[] funcVertex = new Vertex[1]; Vertex[] vertexStack = new Vertex[1]; Graph graph = new Graph(this); graph.graphType = Graph.GraphType.ClassGraph; BuildFuncVertices(graph, ref funcVertex); foreach (FunctionDescriptor fd in functionList) { BuildClassTrace(graph, fd.funcCallStack, fd.functionId, fd.funcSize, funcVertex, ref vertexStack); } foreach (Vertex v in graph.vertices.Values) v.active = true; graph.BottomVertex.active = false; return graph; }
void BuildClassTrace(Graph graph, int stackTraceIndex, int funcIndex, ulong size, Vertex[] funcVertex, ref Vertex[] vertexStack) { string className = ClassNameOfFunc(funcIndex); int functionsToSkip = FunctionsInSameClass(className, stackTraceIndex); int stackPtr = BuildVertexStack(stackTraceIndex, funcVertex, ref vertexStack, 0) - functionsToSkip; Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if (ReadNewLog.InterestingCallStack(vertexStack, stackPtr)) { vertexStack[stackPtr] = graph.FindOrCreateVertex(className, null, null); stackPtr++; stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } if (toVertex != graph.TopVertex) { fromVertex = toVertex; toVertex = graph.BottomVertex; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } } }
void BuildModuleTrace(Graph graph, int stackTraceIndex, int modIndex, ulong size, Vertex[] funcVertex, Vertex[] modVertex, ref Vertex[] vertexStack) { int functionsToSkip = FunctionsInSameModule(modIndex, stackTraceIndex); int stackPtr = BuildVertexStack(stackTraceIndex, funcVertex, ref vertexStack, 0) - functionsToSkip; Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if (ReadNewLog.InterestingCallStack(vertexStack, stackPtr)) { vertexStack[stackPtr] = modVertex[modIndex]; stackPtr++; stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } fromVertex = toVertex; toVertex = graph.BottomVertex; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(size); } }
void BuildModVertices(Graph graph, ref Vertex[] modVertex) { for (int i = 0; i < readNewLog.modBasicName.Length; i++) { string basicName = readNewLog.modBasicName[i]; string fullName = readNewLog.modFullName[i]; if (basicName != null && fullName != null) { readNewLog.AddFunctionVertex(i, basicName, fullName, graph, ref modVertex); modVertex[i].basicName = basicName; modVertex[i].basicSignature = fullName; } } }
internal void BuildHandleAllocationTrace(Graph graph, int stackTraceIndex, uint count, Vertex[] funcVertex, ref Vertex[] vertexStack) { int stackPtr = BuildVertexStack(stackTraceIndex, funcVertex, ref vertexStack, 0); Vertex handleVertex = graph.FindOrCreateVertex("Handle", null, null); handleVertex.interestLevel = InterestLevel.Interesting; Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if (ReadNewLog.InterestingCallStack(vertexStack, stackPtr)) { vertexStack[stackPtr] = handleVertex; stackPtr++; stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(count); } fromVertex = toVertex; toVertex = graph.BottomVertex; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(count); } }
internal Graph BuildAllocationGraph() { Vertex[] typeVertex = new Vertex[1]; Vertex[] funcVertex = new Vertex[1]; Vertex[] vertexStack = new Vertex[1]; Graph graph = new Graph(this); graph.graphType = Graph.GraphType.AllocationGraph; BuildTypeVertices(graph, ref typeVertex); BuildFuncVertices(graph, ref funcVertex); for (int i = 0; i < typeSizeStacktraceToCount.Length; i++) { if (typeSizeStacktraceToCount[i] > 0) { int[] stacktrace = readNewLog.stacktraceTable.IndexToStacktrace(i); int typeIndex = stacktrace[0]; ulong size = (ulong)stacktrace[1] * (ulong)typeSizeStacktraceToCount[i]; BuildAllocationTrace(graph, i, typeIndex, size, typeVertex, funcVertex, ref vertexStack); } } foreach (Vertex v in graph.vertices.Values) v.active = true; graph.BottomVertex.active = false; return graph; }
internal Graph BuildAssemblyGraph() { Vertex[] assemblyVertex = new Vertex[1]; Vertex[] funcVertex = new Vertex[1]; Vertex[] typeVertex = new Vertex[1]; Vertex[] vertexStack = new Vertex[1]; Graph graph = new Graph(this); graph.graphType = Graph.GraphType.AssemblyGraph; int count = BuildAssemblyVertices(graph, ref assemblyVertex); BuildTypeVertices(graph, ref typeVertex); BuildFuncVertices(graph, ref funcVertex); for (int i = 0; i < count; i++) { Vertex v = (Vertex)assemblyVertex[i], tv = null; string c = v.name; int stackid = readNewLog.assemblies[c]; if (stackid < 0) { int[] stacktrace = readNewLog.stacktraceTable.IndexToStacktrace(-stackid); tv = typeVertex[stacktrace[0]]; } BuildAssemblyTrace(graph, stackid, v, tv, funcVertex, ref vertexStack); } foreach (Vertex v in graph.vertices.Values) { v.active = true; } graph.BottomVertex.active = false; return graph; }
static void EnsureVertexCapacity(int id, ref Vertex[] vertexArray) { //Debug.Assert(id >= 0); if (id < vertexArray.Length) return; int newLength = vertexArray.Length * 2; if (newLength <= id) newLength = id + 1; Vertex[] newVertexArray = new Vertex[newLength]; Array.Copy(vertexArray, 0, newVertexArray, 0, vertexArray.Length); vertexArray = newVertexArray; }
internal void AddTypeVertex(int typeId, string typeName, Graph graph, ref Vertex[] typeVertex) { EnsureVertexCapacity(typeId, ref typeVertex); typeVertex[typeId] = graph.FindOrCreateVertex(typeName, null, null); }
internal Vertex CreateVertex(string name, string signature, string key) { Vertex vertex = new Vertex(name, signature, null, this); vertices[key] = vertex; return vertex; }
internal void BuildAssemblyTrace(Graph graph, int stackTraceIndex, Vertex assembly, Vertex typeVertex, Vertex[] funcVertex, ref Vertex[] vertexStack) { int stackPtr = BuildVertexStack(Math.Abs(stackTraceIndex), funcVertex, ref vertexStack, stackTraceIndex < 0 ? 2 : 0); Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if (typeVertex != null) { vertexStack[stackPtr++] = typeVertex; } vertexStack[stackPtr++] = assembly; stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(1); } fromVertex = toVertex; toVertex = graph.BottomVertex; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight(1); }
internal Vertex FindOrCreateVertex(string name, string signature, string module) { string nameSignatureModule = NameSignatureModule(name, signature, module); Vertex vertex; if (!vertices.TryGetValue(nameSignatureModule, out vertex)) { vertex = new Vertex(name, signature, module, this); vertices[nameSignatureModule] = vertex; } return vertex; }
internal void AddFunctionVertex(int funcId, string functionName, string signature, Graph graph, ref Vertex[] funcVertex) { EnsureVertexCapacity(funcId, ref funcVertex); int moduleId = funcModule[funcId]; string moduleName = null; if (moduleId >= 0) moduleName = modBasicName[moduleId]; funcVertex[funcId] = graph.FindOrCreateVertex(functionName, signature, moduleName); }
internal void BuildCallTrace(Graph graph, int stackTraceIndex, Vertex[] funcVertex, ref Vertex[] vertexStack, int count) { int stackPtr = BuildVertexStack(stackTraceIndex, funcVertex, ref vertexStack, 0); Vertex toVertex = graph.TopVertex; Vertex fromVertex; Edge edge; if (ReadNewLog.InterestingCallStack(vertexStack, stackPtr)) { stackPtr = ReadNewLog.FilterVertices(vertexStack, stackPtr); stackPtr = Vertex.SqueezeOutRepetitions(vertexStack, stackPtr); for (int i = 0; i < stackPtr; i++) { fromVertex = toVertex; toVertex = vertexStack[i]; edge = graph.FindOrCreateEdge(fromVertex, toVertex); edge.AddWeight((uint)count); } } }
internal Edge FindOrCreateEdge(Vertex fromVertex, Vertex toVertex) { //Debug.Assert(fromVertex != topVertex || toVertex != bottomVertex); return fromVertex.FindOrCreateOutgoingEdge(toVertex); }
internal int BuildAssemblyVertices(Graph graph, ref Vertex[] typeVertex) { int count = 0; foreach (string c in readNewLog.assemblies.Keys) { readNewLog.AddTypeVertex(count++, c, graph, ref typeVertex); } return count; }
internal void BuildFuncVertices(Graph graph, ref Vertex[] funcVertex) { for (int i = 0; i < readNewLog.funcName.Length; i++) { string name = readNewLog.funcName[i]; string signature = readNewLog.funcSignature[i]; if (name == null) name = string.Format("???? function {0}", i); if (signature == null) signature = "( ???????? )"; readNewLog.AddFunctionVertex(i, name, signature, graph, ref funcVertex); } }
static int LargestRepetition(Vertex[] path, int i, int j, int length) { int len = i; if (len > length - j) len = length - j; for (; len > 0; len--) { int repLen = 0; while (j + repLen + len <= length && IdenticalSequence(path, i - len, j + repLen, len)) repLen += len; if (repLen > 0) return repLen; } return 0; }