public void readLogFile() { log = new ReadNewLog(logFileName); logResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, logResult); }
internal void ViewGraph(ReadLogResult logResult, string exeName, Graph.GraphType graphType) { string fileName = log.fileName; if (exeName != null) fileName = exeName; Graph graph = null; string title = ""; switch (graphType) { case Graph.GraphType.CallGraph: graph = logResult.callstackHistogram.BuildCallGraph(new FilterForm()); graph.graphType = Graph.GraphType.CallGraph; title = "Call Graph for: "; break; case Graph.GraphType.AssemblyGraph: graph = logResult.callstackHistogram.BuildAssemblyGraph(new FilterForm()); graph.graphType = Graph.GraphType.AssemblyGraph; title = "Assembly Graph for: "; break; case Graph.GraphType.AllocationGraph: graph = logResult.allocatedHistogram.BuildAllocationGraph(new FilterForm()); graph.graphType = Graph.GraphType.AllocationGraph; title = "Allocation Graph for: "; break; case Graph.GraphType.HeapGraph: graph = logResult.objectGraph.BuildTypeGraph(new FilterForm()); title = "Heap Graph for: "; break; case Graph.GraphType.FunctionGraph: graph = logResult.functionList.BuildFunctionGraph(new FilterForm()); graph.graphType = Graph.GraphType.FunctionGraph; title = "Function Graph for: "; break; case Graph.GraphType.ModuleGraph: graph = logResult.functionList.BuildModuleGraph(new FilterForm()); graph.graphType = Graph.GraphType.ModuleGraph; title = "Module Graph for: "; break; case Graph.GraphType.ClassGraph: graph = logResult.functionList.BuildClassGraph(new FilterForm()); graph.graphType = Graph.GraphType.ClassGraph; title = "Class Graph for: "; break; default: Debug.Assert(false); break; } title += fileName; GraphViewForm graphViewForm = new GraphViewForm(graph, title); graphViewForm.Visible = true; }
// from form1.cs internal ReadLogResult GetLogResult() { logResult = new ReadLogResult(); logResult.liveObjectTable = new LiveObjectTable(log); logResult.sampleObjectTable = new SampleObjectTable(log); logResult.allocatedHistogram = new Histogram(log); logResult.callstackHistogram = new Histogram(log); logResult.relocatedHistogram = new Histogram(log); logResult.objectGraph = new ObjectGraph(log, 0); logResult.functionList = new FunctionList(log); logResult.hadCallInfo = logResult.hadAllocInfo = false; // We may just have turned a lot of data into garbage - let's try to reclaim the memory GC.Collect(); return logResult; }
private static ReadLogResult GetLogResult(ReadNewLog log) { ReadLogResult readLogResult = new ReadLogResult(); readLogResult.liveObjectTable = new LiveObjectTable(log); readLogResult.sampleObjectTable = new SampleObjectTable(log); readLogResult.allocatedHistogram = new Histogram(log); readLogResult.callstackHistogram = new Histogram(log); readLogResult.relocatedHistogram = new Histogram(log); readLogResult.finalizerHistogram = new Histogram(log); readLogResult.criticalFinalizerHistogram = new Histogram(log); readLogResult.objectGraph = new ObjectGraph(log, 0); readLogResult.functionList = new FunctionList(log); readLogResult.hadCallInfo = readLogResult.hadAllocInfo = false; readLogResult.heapDumpHistograms = new Histogram[0]; return readLogResult; }
public HistogramViewForm() { // // Required for Windows Form Designer support // InitializeComponent(); toolTip = new ToolTip(); toolTip.Active = false; toolTip.ShowAlways = true; toolTip.AutomaticDelay = 70; toolTip.ReshowDelay = 1; autoUpdate = true; lastLogResult = MainForm.instance.lastLogResult; if (lastLogResult != null) { histogram = lastLogResult.allocatedHistogram; typeName = histogram.readNewLog.typeName; } Text = "Histogram by Size for Allocated Objects"; font = MainForm.instance.font; }
internal void GetAllocationGraph(ReadLogResult readLogResult) { graph = readLogResult.allocatedHistogram.BuildAllocationGraph(new FilterForm()); PlaceVertices(); }
private void showHeapGraphMenuItem_Click(object sender, System.EventArgs e) { int endTickIndex = lastTickIndex; if (selectedEndTickIndex != 0) { endTickIndex = selectedEndTickIndex; } ReadNewLog log = sampleObjectTable.readNewLog; long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again ReadLogResult readLogResult = new ReadLogResult(); readLogResult.liveObjectTable = new LiveObjectTable(log); readLogResult.objectGraph = new ObjectGraph(log, 0); log.ReadFile(0, endPos, readLogResult); Graph graph = readLogResult.objectGraph.BuildTypeGraph(new FilterForm()); string title = string.Format("Heap Graph at {0:f3} seconds", lastLog.TickIndexToTime(readLogResult.objectGraph.tickIndex)); GraphViewForm graphViewForm = new GraphViewForm(graph, title); graphViewForm.Visible = true; }
internal SummaryForm(ReadNewLog log, ReadLogResult logResult, string scenario) { // // Required for Windows Form Designer support // InitializeComponent(); this.log = log; this.logResult = logResult; this.scenario = scenario; this.Text = "Summary for " + scenario; FillInNumbers(); EnableDisableButtons(); }
private void readLogFile(ReadNewLog log, ReadLogResult logResult, string exeName, Graph.GraphType graphType) { log.ReadFile(logFileStartOffset, logFileEndOffset, logResult); ViewGraph(logResult, exeName, graphType); }
private void showRelocatedMenuItem_Click(object sender, System.EventArgs e) { int startTickIndex = 0; int endTickIndex = lastTickIndex; if (selectedStartTickIndex != 0) { startTickIndex = selectedStartTickIndex; endTickIndex = selectedEndTickIndex; } ReadNewLog log = sampleObjectTable.readNewLog; long startPos = log.TickIndexToPos(startTickIndex); long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again ReadLogResult readLogResult = new ReadLogResult(); readLogResult.relocatedHistogram = new Histogram(log); readLogResult.liveObjectTable = new LiveObjectTable(log); log.ReadFile(startPos, endPos, readLogResult); // And post it to a new histogram form - hardest part is to compute an appropriate title... string title = string.Format("Histogram by Size for Objects relocated between {0:f3} and {1:f3} seconds", lastLog.TickIndexToTime(startTickIndex), lastLog.TickIndexToTime(endTickIndex)); HistogramViewForm histogramViewForm = new HistogramViewForm(readLogResult.relocatedHistogram, title); histogramViewForm.Show(); }
internal CallTreeForm(string in_logFileName, ReadLogResult in_result) { // open debugging log file // log = new StreamWriter("test.blog"); logFileName = in_logFileName; logResult = in_result; names = logResult.callstackHistogram.readNewLog.funcName; types = logResult.callstackHistogram.readNewLog.typeName; signatures = logResult.callstackHistogram.readNewLog.funcSignature; filterInclude = new FnViewFilter[] { new FnViewFilter(TreeNode.NodeType.Call, -1), new FnViewFilter(TreeNode.NodeType.Call, -1) }; filterExclude = new FnViewFilter[] { new FnViewFilter(TreeNode.NodeType.Call, -1), new FnViewFilter(TreeNode.NodeType.Call, -1) }; fShowSubtree = false; firstNewStack = -1; GetConfiguration(); InitForm( true ); }
private static void AllocationRelocationReport(string logFileName, string startMarker, string endMarker, bool relocationReport) { // first read the entire file ReadNewLog log = new ReadNewLog(logFileName, false); ReadLogResult entireLogResult = GetLogResult(log); log.ReadFile(0, long.MaxValue, entireLogResult); // if we were given a start or an end marker, we need to re-read a portion of the file. ReadLogResult logResult = entireLogResult; if (startMarker != null || endMarker != null) { int startTickIndex = 0; int endTickIndex = entireLogResult.sampleObjectTable.lastTickIndex; if (startMarker != null) { startTickIndex = FindMarkerTickIndex(startMarker, log); } if (endMarker != null) { endTickIndex = FindMarkerTickIndex(endMarker, log); } long startPos = log.TickIndexToPos(startTickIndex); long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again logResult = new ReadLogResult(); if (relocationReport) { logResult.relocatedHistogram = new Histogram(log); logResult.liveObjectTable = new LiveObjectTable(log); } else { logResult.allocatedHistogram = new Histogram(log); } log.ReadFile(startPos, endPos, logResult); if (startMarker == null) { startMarker = CommentRangeForm.startCommentString; } if (endMarker == null) { endMarker = CommentRangeForm.shutdownCommentString; } Console.WriteLine("{0} summary for {1} between {2} ({3} secs) and {4} ({5} secs)", relocationReport ? "Relocation" : "Allocation", logFileName, startMarker, log.TickIndexToTime(startTickIndex), endMarker, log.TickIndexToTime(endTickIndex)); } else { Console.WriteLine("{0} summary for {1}", relocationReport ? "Relocation" : "Allocation", logFileName); } // now we are ready to produce the allocation report from the allocation histogram WriteReport(relocationReport ? logResult.relocatedHistogram : logResult.allocatedHistogram, ""); }
private void showHeapButton_Click(object sender, System.EventArgs e) { forceGcCompletedEvent.Wait(1); forceGcCompletedEvent.Reset(); long startOffset = logFileOffset(); forceGcEvent.Set(); const int maxIter = 10; // give up after ten minutes for (int iter = 0; iter < maxIter; iter++) { long lastOffset = logFileOffset(); if (forceGcCompletedEvent.Wait(60 * 1000)) { forceGcCompletedEvent.Reset(); long saveLogFileStartOffset = logFileStartOffset; logFileStartOffset = startOffset; logFileEndOffset = logFileOffset(); ReadLogResult logResult = GetLogResult(); readLogFile(log, logResult, processFileName, Graph.GraphType.HeapGraph); lastLogResult = logResult; EnableDisableViewMenuItems(); logFileStartOffset = saveLogFileStartOffset; break; } else { // Hmm, the app didn't get back to us in 60 seconds // If the log file is growing, assume the app is still dumping // the heap, otherwise something is obviously wrong. if (logFileOffset() == lastOffset) { MessageBox.Show("There was no response from the application"); break; } } } }
internal static void HeapDumpReport(string logFileName, string startMarker, string endMarker) { ReadNewLog log = new ReadNewLog(logFileName, false); ReadLogResult entireLogResult = GetLogResult(log); log.ReadFile(0, long.MaxValue, entireLogResult); Histogram[] heapDumpHistograms = entireLogResult.heapDumpHistograms; string[] timeMarkers = new String[heapDumpHistograms.Length]; if (startMarker != null || endMarker != null) { int startTickIndex = 0; int endTickIndex = entireLogResult.sampleObjectTable.lastTickIndex; if (startMarker != null) { startTickIndex = FindMarkerTickIndex(startMarker, log); } if (endMarker != null) { endTickIndex = FindMarkerTickIndex(endMarker, log); } int startIndex = 0; int endIndex = 0; for (int i = 0; i < log.heapDumpEventList.count; i++) { if (log.heapDumpEventList.eventTickIndex[i] < startTickIndex) { startIndex = i + 1; } if (log.heapDumpEventList.eventTickIndex[i] < endTickIndex) { endIndex = i + 1; } } if (endMarker == null) { Console.WriteLine("Heap dump for {0} after {1}", logFileName, startMarker); if (startIndex < log.heapDumpEventList.count) { endIndex = startIndex + 1; } else { endIndex = startIndex; } } else { Console.WriteLine("Heap dump for {0} between {1} and {2}", logFileName, startMarker, endMarker); } if (startIndex < endIndex) { heapDumpHistograms = new Histogram[endIndex - startIndex]; for (int i = startIndex; i < endIndex; i++) { heapDumpHistograms[i - startIndex] = entireLogResult.heapDumpHistograms[i]; } timeMarkers = new string[endIndex - startIndex]; } else { heapDumpHistograms = new Histogram[0]; timeMarkers = new string[0]; } } else { Console.WriteLine("Heap dumps for {0}", logFileName); } for (int i = 0; i < timeMarkers.Length; i++) { timeMarkers[i] = string.Format("Heap dump #{0}", i); } if (heapDumpHistograms.Length > 0) { WriteReport(heapDumpHistograms, timeMarkers); } else { Console.WriteLine("***** No heap dumps found *****"); } }
private void profilingActiveCheckBox_CheckedChanged(object sender, System.EventArgs e) { if (allocationsCheckBox.Checked) { ToggleEvent(loggingActiveEvent, loggingActiveCompletedEvent); } if (callsCheckBox.Checked) { ToggleEvent(callGraphActiveEvent, callGraphActiveCompletedEvent); } // disable check boxes if profiling is turned off if (profilingActiveCheckBox.Checked) allocationsCheckBox.Enabled = callsCheckBox.Enabled = targetCLRVersioncomboBox.Enabled = true; else attachProcessButton.Enabled = allocationsCheckBox.Enabled = callsCheckBox.Enabled = targetCLRVersioncomboBox.Enabled = false; enableDisableAttachProcessButtonAndMenuItem(); detachProcessButton.Enabled = false; if (profiledProcess != null && !ProfiledProcessHasExited() && logFileName != null) { if (!File.Exists(logFileName)) { ShowErrorMessage(string.Format("Can not find log file '{0}'.", logFileName)); return; } Stream s = new FileStream(logFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); long offset = s.Length; s.Close(); if (profilingActiveCheckBox.Checked) logFileStartOffset = offset; else { logFileEndOffset = offset; if (logFileStartOffset >= logFileEndOffset && profiledProcess != null && !ProfiledProcessHasExited()) MessageBox.Show("No new data found", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } if (!profilingActiveCheckBox.Checked && logFileStartOffset < logFileEndOffset && logFileName != null) { ReadLogResult readLogResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, readLogResult); lastLogResult = readLogResult; EnableDisableViewMenuItems(); viewSummaryMenuItem_Click(null, null); } } }
private void ResetStateAfterProfilingStopped() { bool connected = profilerConnected; ClearProfiledProcessInfo(); logFileEndOffset = long.MaxValue; if (connected && log != null) { ReadLogResult readLogResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, readLogResult); lastLogResult = readLogResult; EnableDisableViewMenuItems(); ClearEvents(); saveAsMenuItem.Enabled = true; viewSummaryMenuItem_Click(null, null); } EnableDisableLaunchControls(true); detachProcessButton.Enabled = showHeapButton.Enabled = killApplicationButton.Enabled = false; detachProcessMenuItem.Enabled = false; enableDisableAttachProcessButtonAndMenuItem(); }
private ReadLogResult GetLogResult() { ReadLogResult readLogResult = lastLogResult; if (readLogResult == null) { readLogResult = new ReadLogResult(); } readLogResult.liveObjectTable = new LiveObjectTable(log); readLogResult.sampleObjectTable = new SampleObjectTable(log); readLogResult.allocatedHistogram = new Histogram(log); readLogResult.callstackHistogram = new Histogram(log); readLogResult.relocatedHistogram = new Histogram(log); readLogResult.finalizerHistogram = new Histogram(log); readLogResult.criticalFinalizerHistogram = new Histogram(log); readLogResult.createdHandlesHistogram = new Histogram(log); readLogResult.destroyedHandlesHistogram = new Histogram(log); if (readLogResult.objectGraph != null) readLogResult.objectGraph.Neuter(); readLogResult.objectGraph = new ObjectGraph(log, 0); readLogResult.functionList = new FunctionList(log); readLogResult.hadCallInfo = readLogResult.hadAllocInfo = false; readLogResult.handleHash = new Dictionary<ulong, HandleInfo>(); // We may just have turned a lot of data into garbage - let's try to reclaim the memory GC.Collect(); return readLogResult; }
private int WaitForProcessToConnect(string tempDir, string text, bool attachMode = false, uint result = 0) { bool fProfiledProcessInitialized = profiledProcess != null; if (fProfiledProcessInitialized) { if (!VerifyCorrectBitness(profiledProcess)) return -1; } ConnectNamedPipe(handshakingPipeHandle, IntPtr.Zero); ConnectNamedPipe(loggingPipeHandle, IntPtr.Zero); int pid = 0; byte[] handshakingBuffer = new byte[9]; int handshakingReadBytes = 0; // IMPORTANT: maxloggingBufferSize must match bufferSize defined in ProfilerCallback.cpp. const int maxloggingBufferSize = 512; byte[] loggingBuffer = new byte[maxloggingBufferSize]; int loggingReadBytes = 0; WaitingForConnectionForm waitingForConnectionForm = null; int beginTickCount = Environment.TickCount; //Do not show the text in attachmode if (attachMode == false) { if (noUI) { Console.WriteLine(text); } else { if (waitingForConnectionForm == null) waitingForConnectionForm = new WaitingForConnectionForm(); waitingForConnectionForm.setMessage(text); waitingForConnectionForm.Visible = true; } } // loop reading two pipes, // until // (1)successfully connected // (2)User canceled // (3)attach failed // (4)target process exited while (true) { #region handshaking //(1)succeeded try { handshakingReadBytes += handshakingPipe.Read(handshakingBuffer, handshakingReadBytes, 9 - handshakingReadBytes); } catch (System.IO.IOException) { } //Read 9 bytes from handshaking pipe //means the profielr was initialized successfully if (handshakingReadBytes == 9) break; Application.DoEvents(); // (2)User canceled if (!noUI) { if (waitingForConnectionForm != null && waitingForConnectionForm.DialogResult == DialogResult.Cancel) { pid = -1; break; } } #endregion handshaking #region logging // (3)attach failed // (3.1) read logging message // (3.2) break if attach failed. // (3.1) read logging message try { loggingReadBytes += loggingPipe.Read(loggingBuffer, loggingReadBytes, maxloggingBufferSize - loggingReadBytes); } catch (System.IO.IOException) { } if (loggingReadBytes == maxloggingBufferSize) { char[] charBuffer = new char[loggingReadBytes]; for (int i = 0; i < loggingReadBytes; i++) charBuffer[i] = Convert.ToChar(loggingBuffer[i]); string message = new String(charBuffer, 0, loggingReadBytes); if (attachMode == false && noUI == false) { waitingForConnectionForm.addMessage(message); } else { ShowErrorMessage(message); } loggingReadBytes = 0; while (true) { try { if (loggingPipe.Read(loggingBuffer, 0, 1) == 0) { DisconnectNamedPipe(loggingPipeHandle); ConnectNamedPipe(loggingPipeHandle, IntPtr.Zero); break; } } catch (System.IO.IOException) { DisconnectNamedPipe(loggingPipeHandle); ConnectNamedPipe(loggingPipeHandle, IntPtr.Zero); break; } } } // (3.2) break if attach failed. if (attachMode == true && result != 0) { pid = -1; break; } #endregion logging // (4)target process exited if ((fProfiledProcessInitialized && profiledProcess == null) || (profiledProcess != null && ProfiledProcessHasExited())) { pid = -1; break; } Thread.Sleep(100); } if (waitingForConnectionForm != null) waitingForConnectionForm.Visible = false; if (pid == -1) return pid; if (handshakingReadBytes == 9) { char[] charBuffer = new char[9]; for (int i = 0; i < handshakingBuffer.Length; i++) charBuffer[i] = Convert.ToChar(handshakingBuffer[i]); pid = Int32.Parse(new String(charBuffer, 0, 8), NumberStyles.HexNumber); CreateEvents(pid); string fileName = getLogFileName(pid); byte[] fileNameBuffer = new Byte[fileName.Length + 1]; for (int i = 0; i < fileName.Length; i++) fileNameBuffer[i] = (byte)fileName[i]; fileNameBuffer[fileName.Length] = 0; handshakingPipe.Write(fileNameBuffer, 0, fileNameBuffer.Length); handshakingPipe.Flush(); logFileName = tempDir + "\\" + fileName; log = new ReadNewLog(logFileName); lastLogResult = null; ObjectGraph.cachedGraph = null; while (true) { try { if (handshakingPipe.Read(handshakingBuffer, 0, 1) == 0) // && GetLastError() == 109/*ERROR_BROKEN_PIPE*/) { DisconnectNamedPipe(handshakingPipeHandle); ConnectNamedPipe(handshakingPipeHandle, IntPtr.Zero); break; } } catch (System.IO.IOException) { DisconnectNamedPipe(handshakingPipeHandle); ConnectNamedPipe(handshakingPipeHandle, IntPtr.Zero); break; } } } else { string error = string.Format("Error {0} occurred", GetLastError()); ShowErrorMessage(error); } if (noUI) { Console.WriteLine("CLRProfiler is loaded in the target process."); } else { EnableDisableViewMenuItems(); EnableDisableLaunchControls(false); if (!allocationsCheckBox.Checked && callsCheckBox.Checked) showHeapButton.Enabled = false; else showHeapButton.Enabled = true; killApplicationButton.Enabled = true; detachProcessMenuItem.Enabled = false; } logFileStartOffset = 0; logFileEndOffset = long.MaxValue; profilerConnected = true; return pid; }
private void LoadLogFile(string logFileName) { if (logFileName.EndsWith(".exe", //The string to compare to the substring at the end of this instance true, //true to ignore case during the comparison; otherwise, false. CultureInfo.InvariantCulture //An invariant culture is culture-insensitive. )) { ShowErrorMessage(logFileName +" is not a valid CLRProfiler log file name."); Environment.ExitCode = 1; exitProgram = true; return; } this.logFileName = logFileName; logFileStartOffset = 0; logFileEndOffset = long.MaxValue; processFileName = null; log = new ReadNewLog(logFileName); lastLogResult = null; ObjectGraph.cachedGraph = null; ReadLogResult readLogResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, readLogResult); lastLogResult = readLogResult; Text = "Analyzing " + logFileName; EnableDisableViewMenuItems(); viewSummaryMenuItem_Click(null, null); }
public void readLogFile() { log = new ReadNewLog(LogFileName); logResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, logResult); }
/// <summary> /// Added by Sonal: /// Writes Difference between two heap dumps /// </summary> /// <param name="histogram"></param> /// <param name="timeMarker"></param> private static void WriteDiffReport(Histogram[] histogram, string[] timeMarker, ReadLogResult entireLogResult) { TypeDescriptor[] typeIndexToTypeDescriptor = new TypeDescriptor[histogram[0].readNewLog.typeName.Length]; int[] totalSize = new int[histogram.Length]; int[] totalCount = new int[histogram.Length]; for (int h = 0; h < histogram.Length; h++) { int[] typeSizeStacktraceToCount = histogram[h].typeSizeStacktraceToCount; for (int i = 0; i < typeSizeStacktraceToCount.Length; i++) { int count = typeSizeStacktraceToCount[i]; if (count == 0) continue; int[] stacktrace = histogram[h].readNewLog.stacktraceTable.IndexToStacktrace(i); int typeIndex = stacktrace[0]; int size = stacktrace[1]; if (typeIndexToTypeDescriptor[typeIndex] == null) typeIndexToTypeDescriptor[typeIndex] = new TypeDescriptor(typeIndex, histogram.Length); typeIndexToTypeDescriptor[typeIndex].size[h] += size * count; typeIndexToTypeDescriptor[typeIndex].count[h] += count; totalSize[h] += size * count; totalCount[h] += count; } } ArrayList al = new ArrayList(); for (int i = 0; i < typeIndexToTypeDescriptor.Length; i++) { if (typeIndexToTypeDescriptor[i] == null) continue; al.Add(typeIndexToTypeDescriptor[i]); } al.Sort(); Console.WriteLine("<?xml version=\"1.0\"?>"); Console.WriteLine("<DetailedLeakReport>"); Console.WriteLine("<LeakSummary>"); int counter = 0; foreach (TypeDescriptor td in al) { int diffCount = td.count[histogram.Length - 1] - td.count[0]; int diffSize = td.size[histogram.Length - 1] - td.size[0]; if (diffCount > 0) { counter++; Console.WriteLine("<Object>"); Console.WriteLine("<Counter>{0}</Counter>", counter); Console.WriteLine("<ObjectName><!--{0}--></ObjectName>", histogram[0].readNewLog.typeName[td.typeIndex]); for (int h = 0; h < histogram.Length; h++) { Console.WriteLine("<CheckPoint{0}>", h + 1); Console.WriteLine("<Instances>{0}</Instances>", td.count[h]); Console.WriteLine("<Size>{0}</Size>", td.size[h]); Console.WriteLine("</CheckPoint{0}>", h + 1); } Console.WriteLine("<Difference>"); Console.WriteLine("<Instances>{0}</Instances>", diffCount); Console.WriteLine("<Size>{0}</Size>", diffSize); Console.WriteLine("</Difference>"); Console.WriteLine("</Object>"); } } Console.WriteLine("</LeakSummary>"); Console.WriteLine("<LeakDetails>"); counter = 0; foreach (TypeDescriptor td in al) { int diffCount = td.count[histogram.Length - 1] - td.count[0]; int diffSize = td.size[histogram.Length - 1] - td.size[0]; if (diffCount > 0) { counter++; Console.WriteLine("<LeakedObject>"); Console.WriteLine("<Summary>"); Console.WriteLine("<Counter>{0}</Counter>", counter); Console.WriteLine("<ObjectName><!--{0}--></ObjectName>", histogram[0].readNewLog.typeName[td.typeIndex]); for (int h = 0; h < histogram.Length; h++) { Console.WriteLine("<CheckPoint{0}>", h + 1); Console.WriteLine("<Instances>{0}</Instances>", td.count[h]); Console.WriteLine("<Size>{0}</Size>", td.size[h]); Console.WriteLine("</CheckPoint{0}>", h + 1); } Console.WriteLine("<Difference>"); Console.WriteLine("<Instances>{0}</Instances>", diffCount); Console.WriteLine("<Size>{0}</Size>", diffSize); if (entireLogResult.requestedObjectGraph != null) entireLogResult.requestedObjectGraph.WriteVertexPaths(histogram[0].tickIndex, histogram[histogram.Length - 1].tickIndex, histogram[0].readNewLog.typeName[td.typeIndex]); else if (entireLogResult.objectGraph != null) entireLogResult.objectGraph.WriteVertexPaths(histogram[0].tickIndex, histogram[histogram.Length - 1].tickIndex, histogram[0].readNewLog.typeName[td.typeIndex]); Console.WriteLine("</LeakedObject>"); } } Console.WriteLine("</LeakDetails>"); Console.WriteLine("</DetailedLeakReport>"); }
internal CallTreeForm(string in_logFileName, ReadLogResult in_result, bool forCompare) { this.forCompare = forCompare; logFileName = in_logFileName; logResult = in_result; names = logResult.callstackHistogram.readNewLog.funcName; types = logResult.callstackHistogram.readNewLog.typeName; signatures = logResult.callstackHistogram.readNewLog.funcSignature; filterInclude = new FnViewFilter[] { new FnViewFilter(TreeNode.NodeType.Call, -1), new FnViewFilter(TreeNode.NodeType.Call, -1) }; filterExclude = new FnViewFilter[] { new FnViewFilter(TreeNode.NodeType.Call, -1), new FnViewFilter(TreeNode.NodeType.Call, -1) }; fShowSubtree = false; firstNewStack = -1; GetConfiguration(); InitForm( true ); }
internal static Histogram GetSurvivorHistogram(ReadNewLog log, ReadLogResult entireLogResult, int startTickIndex, int endTickIndex, string timeMarker) { ReadLogResult logResult = entireLogResult; int timeTickIndex = entireLogResult.sampleObjectTable.lastTickIndex; if (timeMarker != null) { timeTickIndex = FindMarkerTickIndex(timeMarker, log); long endPos = log.TickIndexToPos(timeTickIndex); // Read the selected portion of the log again logResult = new ReadLogResult(); logResult.liveObjectTable = new LiveObjectTable(log); log.ReadFile(0, endPos, logResult); } Histogram histogram = new Histogram(log); LiveObjectTable.LiveObject o; for (logResult.liveObjectTable.GetNextObject(0, ulong.MaxValue, out o); o.id < ulong.MaxValue; logResult.liveObjectTable.GetNextObject(o.id + o.size, ulong.MaxValue, out o)) { if (startTickIndex <= o.allocTickIndex && o.allocTickIndex < endTickIndex) histogram.AddObject(o.typeSizeStacktraceIndex, 1); } return histogram; }
/// <summary> /// Added by Sonal: /// Writes Difference between two heap dumps /// </summary> /// <param name="histogram"></param> /// <param name="timeMarker"></param> private static void WriteDiffReport(Histogram[] histogram, string[] timeMarker, ReadLogResult entireLogResult) { TypeDescriptor[] typeIndexToTypeDescriptor = new TypeDescriptor[histogram[0].readNewLog.typeName.Length]; int[] totalSize = new int[histogram.Length]; int[] totalCount = new int[histogram.Length]; for (int h = 0; h < histogram.Length; h++) { int[] typeSizeStacktraceToCount = histogram[h].typeSizeStacktraceToCount; for (int i = 0; i < typeSizeStacktraceToCount.Length; i++) { int count = typeSizeStacktraceToCount[i]; if (count == 0) { continue; } int[] stacktrace = histogram[h].readNewLog.stacktraceTable.IndexToStacktrace(i); int typeIndex = stacktrace[0]; int size = stacktrace[1]; if (typeIndexToTypeDescriptor[typeIndex] == null) { typeIndexToTypeDescriptor[typeIndex] = new TypeDescriptor(typeIndex, histogram.Length); } typeIndexToTypeDescriptor[typeIndex].size[h] += size * count; typeIndexToTypeDescriptor[typeIndex].count[h] += count; totalSize[h] += size * count; totalCount[h] += count; } } ArrayList al = new ArrayList(); for (int i = 0; i < typeIndexToTypeDescriptor.Length; i++) { if (typeIndexToTypeDescriptor[i] == null) { continue; } al.Add(typeIndexToTypeDescriptor[i]); } al.Sort(); Console.WriteLine("<?xml version=\"1.0\"?>"); Console.WriteLine("<DetailedLeakReport>"); Console.WriteLine("<LeakSummary>"); int counter = 0; foreach (TypeDescriptor td in al) { int diffCount = td.count[histogram.Length - 1] - td.count[0]; int diffSize = td.size[histogram.Length - 1] - td.size[0]; if (diffCount > 0) { counter++; Console.WriteLine("<Object>"); Console.WriteLine("<Counter>{0}</Counter>", counter); Console.WriteLine("<ObjectName><!--{0}--></ObjectName>", histogram[0].readNewLog.typeName[td.typeIndex]); for (int h = 0; h < histogram.Length; h++) { Console.WriteLine("<CheckPoint{0}>", h + 1); Console.WriteLine("<Instances>{0}</Instances>", td.count[h]); Console.WriteLine("<Size>{0}</Size>", td.size[h]); Console.WriteLine("</CheckPoint{0}>", h + 1); } Console.WriteLine("<Difference>"); Console.WriteLine("<Instances>{0}</Instances>", diffCount); Console.WriteLine("<Size>{0}</Size>", diffSize); Console.WriteLine("</Difference>"); Console.WriteLine("</Object>"); } } Console.WriteLine("</LeakSummary>"); Console.WriteLine("<LeakDetails>"); counter = 0; foreach (TypeDescriptor td in al) { int diffCount = td.count[histogram.Length - 1] - td.count[0]; int diffSize = td.size[histogram.Length - 1] - td.size[0]; if (diffCount > 0) { counter++; Console.WriteLine("<LeakedObject>"); Console.WriteLine("<Summary>"); Console.WriteLine("<Counter>{0}</Counter>", counter); Console.WriteLine("<ObjectName><!--{0}--></ObjectName>", histogram[0].readNewLog.typeName[td.typeIndex]); for (int h = 0; h < histogram.Length; h++) { Console.WriteLine("<CheckPoint{0}>", h + 1); Console.WriteLine("<Instances>{0}</Instances>", td.count[h]); Console.WriteLine("<Size>{0}</Size>", td.size[h]); Console.WriteLine("</CheckPoint{0}>", h + 1); } Console.WriteLine("<Difference>"); Console.WriteLine("<Instances>{0}</Instances>", diffCount); Console.WriteLine("<Size>{0}</Size>", diffSize); if (entireLogResult.requestedObjectGraph != null) { entireLogResult.requestedObjectGraph.WriteVertexPaths(histogram[0].tickIndex, histogram[histogram.Length - 1].tickIndex, histogram[0].readNewLog.typeName[td.typeIndex]); } else if (entireLogResult.objectGraph != null) { entireLogResult.objectGraph.WriteVertexPaths(histogram[0].tickIndex, histogram[histogram.Length - 1].tickIndex, histogram[0].readNewLog.typeName[td.typeIndex]); } Console.WriteLine("</LeakedObject>"); } } Console.WriteLine("</LeakDetails>"); Console.WriteLine("</DetailedLeakReport>"); }
internal void ViewGraph(ReadLogResult logResult, string exeName, Graph.GraphType graphType) { string fileName = log.fileName; if (exeName != null) { fileName = exeName; } Graph graph = null; string title = ""; switch (graphType) { case Graph.GraphType.CallGraph: graph = logResult.callstackHistogram.BuildCallGraph(new FilterForm()); graph.graphType = Graph.GraphType.CallGraph; title = "Call Graph for: "; break; case Graph.GraphType.AssemblyGraph: graph = logResult.callstackHistogram.BuildAssemblyGraph(new FilterForm()); graph.graphType = Graph.GraphType.AssemblyGraph; title = "Assembly Graph for: "; break; case Graph.GraphType.AllocationGraph: graph = logResult.allocatedHistogram.BuildAllocationGraph(new FilterForm()); graph.graphType = Graph.GraphType.AllocationGraph; title = "Allocation Graph for: "; break; case Graph.GraphType.HeapGraph: graph = logResult.objectGraph.BuildTypeGraph(new FilterForm()); title = "Heap Graph for: "; break; case Graph.GraphType.FunctionGraph: graph = logResult.functionList.BuildFunctionGraph(new FilterForm()); graph.graphType = Graph.GraphType.FunctionGraph; title = "Function Graph for: "; break; case Graph.GraphType.ModuleGraph: graph = logResult.functionList.BuildModuleGraph(new FilterForm()); graph.graphType = Graph.GraphType.ModuleGraph; title = "Module Graph for: "; break; case Graph.GraphType.ClassGraph: graph = logResult.functionList.BuildClassGraph(new FilterForm()); graph.graphType = Graph.GraphType.ClassGraph; title = "Class Graph for: "; break; default: Debug.Assert(false); break; } title += fileName; GraphViewForm graphViewForm = new GraphViewForm(graph, title); graphViewForm.Visible = true; }
/// <summary> /// Sonal: Function to generate and print Leak Report for the dump file. /// </summary> /// <param name="logFileName">dump file name</param> /// <param name="startMarker">int {0,NumHeapDumps}</param> /// <param name="endMarker">int {0,NumHeapDumps}</param> internal static void LeakReport(string logFileName, string startMarker, string endMarker) { if (startMarker == null) { startMarker = "1"; } if (endMarker == null) { endMarker = "2"; } int startIndex; int endIndex; try { startIndex = int.Parse(startMarker); endIndex = int.Parse(endMarker); } catch { throw new ArgumentException("Markers have to be positive integral values"); } startIndex--; endIndex--; if ((startIndex < 0) || (endIndex < 0)) { throw new ArgumentException("Markers can not be negative"); } ReadNewLog log = new ReadNewLog(logFileName, false); ReadLogResult entireLogResult = GetLogResult(log); log.ReadFile(0, long.MaxValue, entireLogResult, endIndex + 1); if (entireLogResult.requestedObjectGraph == null) { throw new ArgumentException("Invalid EndIndex"); } Histogram[] heapDumpHistograms = entireLogResult.heapDumpHistograms; string[] timeMarkers = new String[2]; if (startIndex < endIndex) { heapDumpHistograms = new Histogram[endIndex - startIndex + 1]; for (int i = startIndex; i <= endIndex; i++) { heapDumpHistograms[i - startIndex] = entireLogResult.heapDumpHistograms[i]; } timeMarkers = new string[endIndex - startIndex + 1]; } else { heapDumpHistograms = new Histogram[0]; timeMarkers = new string[0]; } for (int i = 0; i < timeMarkers.Length; i++) { timeMarkers[i] = string.Format("Heap dump #{0}", i + 1); } if (heapDumpHistograms.Length > 0) { WriteDiffReport(heapDumpHistograms, timeMarkers, entireLogResult); } else { Console.WriteLine("***** No heap dumps found *****"); } }
internal void LoadLogFile(string logFileName) { this.logFileName = logFileName; logFileStartOffset = 0; logFileEndOffset = long.MaxValue; log = new ReadNewLog(logFileName); lastLogResult = null; ObjectGraph.cachedGraph = null; ReadLogResult readLogResult = GetLogResult(); log.ReadFile(logFileStartOffset, logFileEndOffset, readLogResult); lastLogResult = readLogResult; viewSummaryMenuItem_Click(null, null); }
internal void ReadFile(long startFileOffset, long endFileOffset, ReadLogResult readLogResult) { ProgressForm progressForm = new ProgressForm(); progressForm.Text = string.Format("Progress loading {0}", fileName); progressForm.Visible = progressFormVisible; progressForm.setProgress(0); if (stacktraceTable == null) stacktraceTable = new StacktraceTable(); if (timePos == null) timePos = new TimePos[1000]; AddTypeName(0, "Free Space"); try { Stream s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); r = new StreamReader(s); for (timePosIndex = timePosCount; timePosIndex > 0; timePosIndex--) if (timePos[timePosIndex-1].pos <= startFileOffset) break; // start at the beginning if no later start point available or asked for info that can only // be constructed by reading the whole file. if (timePosIndex <= 1 || readLogResult.relocatedHistogram != null || readLogResult.finalizerHistogram != null || readLogResult.criticalFinalizerHistogram != null || readLogResult.liveObjectTable != null) { pos = 0; timePosIndex = 1; } else { timePosIndex--; pos = timePos[timePosIndex].pos; } if (timePosCount == 0) { timePos[0] = new TimePos(0.0, 0); timePosCount = timePosIndex = 1; } s.Position = pos; buffer = new byte[4096]; bufPos = 0; bufLevel = 0; int maxProgress = (int)(r.BaseStream.Length/1024); progressForm.setMaximum(maxProgress); line = 1; StringBuilder sb = new StringBuilder(); ulong[] ulongStack = new ulong[1000]; int[] intStack = new int[1000]; int stackPtr = 0; c = ReadChar(); bool thisIsR = false, previousWasR; bool extendedRootInfoSeen = false; int lastTickIndex = 0; bool newGcEvent = false; while (c != -1) { if (pos > endFileOffset) break; if ((line % 1024) == 0) { int currentProgress = (int)(pos/1024); if (currentProgress <= maxProgress) { progressForm.setProgress(currentProgress); Application.DoEvents(); if (progressForm.DialogResult == DialogResult.Cancel) break; } } lastLineStartPos = pos-1; previousWasR = thisIsR; thisIsR = false; switch (c) { case -1: break; case 'F': case 'f': { c = ReadChar(); int funcIndex = ReadInt(); while (c == ' ' || c == '\t') c = ReadChar(); sb.Length = 0; // Name may contain spaces if they are in angle brackets. // Example: <Module>::std_less<unsigned void>.() // The name may be truncated at 255 chars by profilerOBJ.dll int angleBracketsScope = 0; while (c > ' ' || angleBracketsScope != 0 && sb.Length < 255) { if (c == '<') angleBracketsScope++; sb.Append((char)c); c = ReadChar(); if (c == '>' && angleBracketsScope > 0) angleBracketsScope--; } string name = sb.ToString(); while (c == ' ' || c == '\t') c = ReadChar(); sb.Length = 0; while (c > '\r') { sb.Append((char)c); if (c == ')') { c = ReadChar(); break; } c = ReadChar(); } string signature = sb.ToString(); ulong addr = ReadULong(); uint size = ReadUInt(); int modIndex = ReadInt(); int stackIndex = ReadInt(); if (c != -1) { EnsureStringCapacity(funcIndex, ref funcName); funcName[funcIndex] = name; EnsureStringCapacity(funcIndex, ref funcSignature); funcSignature[funcIndex] = signature; EnsureIntCapacity(funcIndex, ref funcModule); funcModule[funcIndex] = modIndex; string nameAndSignature = name; if (signature != null) nameAndSignature = name + ' '+signature; if (stackIndex >= 0 && readLogResult.functionList != null) { funcSignatureIdHash[nameAndSignature] = funcIndex; readLogResult.functionList.Add(funcIndex, stackIndex, size, modIndex); } } break; } case 'T': case 't': { c = ReadChar(); int typeIndex = ReadInt(); while (c == ' ' || c == '\t') c = ReadChar(); if (c != -1 && Char.IsDigit((char)c)) { if (ReadInt() != 0) { finalizableTypes[typeIndex] = true; } } while (c == ' ' || c == '\t') c = ReadChar(); sb.Length = 0; while (c > '\r') { sb.Append((char)c); c = ReadChar(); } string typeName = sb.ToString(); if (c != -1) { AddTypeName(typeIndex, typeName); } break; } // 'A' with thread identifier case '!': { c = ReadChar(); int threadId = ReadInt(); ulong id = ReadULong(); int typeSizeStackTraceIndex = ReadInt(); typeSizeStackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(typeSizeStackTraceIndex); if (c != -1) { if (readLogResult.liveObjectTable != null) readLogResult.liveObjectTable.InsertObject(id, typeSizeStackTraceIndex, lastTickIndex, lastTickIndex, true, readLogResult.sampleObjectTable); if (pos >= startFileOffset && pos < endFileOffset && readLogResult.allocatedHistogram != null) { // readLogResult.calls.Add(new CallOrAlloc(false, threadId, typeSizeStackTraceIndex)); readLogResult.allocatedHistogram.AddObject(typeSizeStackTraceIndex, 1); } List<string> prev; if (assembliesJustLoaded.TryGetValue(threadId, out prev) && prev.Count != 0) { foreach(string assemblyName in prev) { assemblies[assemblyName] = -typeSizeStackTraceIndex; } prev.Clear(); } } readLogResult.hadAllocInfo = true; readLogResult.hadCallInfo = true; break; } case 'A': case 'a': { c = ReadChar(); ulong id = ReadULong(); int typeSizeStackTraceIndex = ReadInt(); typeSizeStackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(typeSizeStackTraceIndex); if (c != -1) { if (readLogResult.liveObjectTable != null) readLogResult.liveObjectTable.InsertObject(id, typeSizeStackTraceIndex, lastTickIndex, lastTickIndex, true, readLogResult.sampleObjectTable); if (pos >= startFileOffset && pos < endFileOffset && readLogResult.allocatedHistogram != null) { // readLogResult.calls.Add(new CallOrAlloc(false, typeSizeStackTraceIndex)); readLogResult.allocatedHistogram.AddObject(typeSizeStackTraceIndex, 1); } } readLogResult.hadAllocInfo = true; readLogResult.hadCallInfo = true; break; } case 'C': case 'c': { c = ReadChar(); if (pos < startFileOffset || pos >= endFileOffset) { while (c >= ' ') c = ReadChar(); break; } int threadIndex = ReadInt(); int stackTraceIndex = ReadInt(); stackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(stackTraceIndex); if (c != -1) { if (readLogResult.callstackHistogram != null) { readLogResult.callstackHistogram.AddObject(stackTraceIndex, 1); } List<string> prev; if (assembliesJustLoaded.TryGetValue(threadIndex, out prev) && prev.Count != 0) { foreach(string assemblyName in prev) { assemblies[assemblyName] = stackTraceIndex; } prev.Clear(); } } readLogResult.hadCallInfo = true; break; } case 'E': case 'e': { c = ReadChar(); extendedRootInfoSeen = true; thisIsR = true; if (pos < startFileOffset || pos >= endFileOffset) { while (c >= ' ') c = ReadChar(); break; } if (!previousWasR) { heapDumpEventList.AddEvent(lastTickIndex, null); if (readLogResult.objectGraph != null && !readLogResult.objectGraph.empty) { readLogResult.objectGraph.BuildTypeGraph(new FilterForm()); readLogResult.objectGraph.Neuter(); } readLogResult.objectGraph = new ObjectGraph(this, lastTickIndex); Histogram[] h = readLogResult.heapDumpHistograms; if (h != null) { readLogResult.heapDumpHistograms = new Histogram[h.Length+1]; for (int i = 0; i < h.Length; i++) readLogResult.heapDumpHistograms[i] = h[i]; readLogResult.heapDumpHistograms[h.Length] = new Histogram(this); } } ulong objectID = ReadULong(); GcRootKind rootKind = (GcRootKind)ReadInt(); GcRootFlags rootFlags = (GcRootFlags)ReadInt(); ulong rootID = ReadULong(); ObjectGraph objectGraph = readLogResult.objectGraph; if (c != -1 && objectID > 0 && objectGraph != null && (rootFlags & GcRootFlags.WeakRef) == 0) { string rootName; switch (rootKind) { case GcRootKind.Stack: rootName = "Stack"; break; case GcRootKind.Finalizer: rootName = "Finalizer"; break; case GcRootKind.Handle: rootName = "Handle"; break; default: rootName = "Other"; break; } if ((rootFlags & GcRootFlags.Pinning) != 0) rootName += ", Pinning"; if ((rootFlags & GcRootFlags.WeakRef) != 0) rootName += ", WeakRef"; if ((rootFlags & GcRootFlags.Interior) != 0) rootName += ", Interior"; if ((rootFlags & GcRootFlags.Refcounted) != 0) rootName += ", RefCounted"; int rootTypeId = objectGraph.GetOrCreateGcType(rootName); ulongStack[0] = objectID; ObjectGraph.GcObject rootObject = objectGraph.CreateObject(rootTypeId, 1, ulongStack); objectGraph.AddRootObject(rootObject, rootID); } break; } case 'R': case 'r': { c = ReadChar(); thisIsR = true; if (extendedRootInfoSeen || pos < startFileOffset || pos >= endFileOffset) { while (c >= ' ') c = ReadChar(); break; } if (!previousWasR) { heapDumpEventList.AddEvent(lastTickIndex, null); if (readLogResult.objectGraph != null && !readLogResult.objectGraph.empty) { readLogResult.objectGraph.BuildTypeGraph(new FilterForm()); readLogResult.objectGraph.Neuter(); } readLogResult.objectGraph = new ObjectGraph(this, lastTickIndex); Histogram[] h = readLogResult.heapDumpHistograms; if (h != null) { readLogResult.heapDumpHistograms = new Histogram[h.Length+1]; for (int i = 0; i < h.Length; i++) readLogResult.heapDumpHistograms[i] = h[i]; readLogResult.heapDumpHistograms[h.Length] = new Histogram(this); } } stackPtr = 0; ulong objectID; while ((objectID = ReadULong()) != ulong.MaxValue) { if (objectID > 0) { ulongStack[stackPtr] = objectID; stackPtr++; if (stackPtr >= ulongStack.Length) ulongStack = GrowULongVector(ulongStack); } } if (c != -1) { if (readLogResult.objectGraph != null) readLogResult.objectGraph.AddRoots(stackPtr, ulongStack); } break; } case 'O': case 'o': { c = ReadChar(); if (pos < startFileOffset || pos >= endFileOffset || readLogResult.objectGraph == null) { while (c >= ' ') c = ReadChar(); break; } ulong objectId = ReadULong(); int typeIndex = ReadInt(); uint size = ReadUInt(); stackPtr = 0; ulong objectID; while ((objectID = ReadULong()) != ulong.MaxValue) { if (objectID > 0) { ulongStack[stackPtr] = objectID; stackPtr++; if (stackPtr >= ulongStack.Length) ulongStack = GrowULongVector(ulongStack); } } if (c != -1) { ObjectGraph objectGraph = readLogResult.objectGraph; objectGraph.GetOrCreateGcType(typeIndex); int typeSizeStackTraceId = -1; int allocTickIndex = 0; // try to find the allocation stack trace and allocation time // from the live object table if (readLogResult.liveObjectTable != null) { LiveObjectTable.LiveObject liveObject; readLogResult.liveObjectTable.GetNextObject(objectId, objectId, out liveObject); if (liveObject.id == objectId) { typeSizeStackTraceId = liveObject.typeSizeStacktraceIndex; allocTickIndex = liveObject.allocTickIndex; Histogram[] h = readLogResult.heapDumpHistograms; if (h != null) h[h.Length-1].AddObject(liveObject.typeSizeStacktraceIndex, 1); } } if (typeSizeStackTraceId == -1) typeSizeStackTraceId = stacktraceTable.GetOrCreateTypeSizeId(typeIndex, (int)size); ObjectGraph.GcObject gcObject = objectGraph.CreateAndEnterObject(objectId, typeSizeStackTraceId, stackPtr, ulongStack); gcObject.AllocTickIndex = allocTickIndex; } break; } case 'M': case 'm': { c = ReadChar(); int modIndex = ReadInt(); sb.Length = 0; while (c > '\r') { sb.Append((char)c); c = ReadChar(); } if (c != -1) { string lineString = sb.ToString(); int addrPos = lineString.LastIndexOf(" 0x"); if (addrPos <= 0) addrPos = lineString.Length; int backSlashPos = lineString.LastIndexOf(@"\"); if (backSlashPos <= 0) backSlashPos = -1; string basicName = lineString.Substring(backSlashPos + 1, addrPos - backSlashPos - 1); string fullName = lineString.Substring(0, addrPos); EnsureStringCapacity(modIndex, ref modBasicName); modBasicName[modIndex] = basicName; EnsureStringCapacity(modIndex, ref modFullName); modFullName[modIndex] = fullName; } break; } case 'U': case 'u': { c = ReadChar(); ulong oldId = ReadULong(); ulong newId = ReadULong(); uint length = ReadUInt(); Histogram reloHist = null; if (pos >= startFileOffset && pos < endFileOffset) reloHist = readLogResult.relocatedHistogram; if (readLogResult.liveObjectTable != null) readLogResult.liveObjectTable.UpdateObjects(reloHist, oldId, newId, length, lastTickIndex, readLogResult.sampleObjectTable); break; } case 'V': case 'v': { c = ReadChar(); ulong startId = ReadULong(); uint length = ReadUInt(); Histogram reloHist = null; if (pos >= startFileOffset && pos < endFileOffset) reloHist = readLogResult.relocatedHistogram; if (readLogResult.liveObjectTable != null) readLogResult.liveObjectTable.UpdateObjects(reloHist, startId, startId, length, lastTickIndex, readLogResult.sampleObjectTable); break; } case 'B': case 'b': c = ReadChar(); int startGC = ReadInt(); int induced = ReadInt(); int condemnedGeneration = ReadInt(); if (startGC != 0) newGcEvent = gcEventList.AddEvent(lastTickIndex, null); if (newGcEvent) { if (startGC != 0) { if (induced != 0) { for (int gen = 0; gen <= condemnedGeneration; gen++) inducedGcCount[gen]++; } } else { int condemnedLimit = condemnedGeneration; if (condemnedLimit == 2) condemnedLimit = 3; for (int gen = 0; gen <= condemnedLimit; gen++) { cumulativeGenerationSize[gen] += generationSize[gen]; gcCount[gen]++; } } } for (int gen = 0; gen <= 3; gen++) generationSize[gen] = 0; while (c >= ' ') { ulong rangeStart = ReadULong(); ulong rangeLength = ReadULong(); ulong rangeLengthReserved = ReadULong(); int rangeGeneration = ReadInt(); if (c == -1 || rangeGeneration < 0) break; if (readLogResult.liveObjectTable != null) { if (startGC != 0) { if (rangeGeneration > condemnedGeneration && condemnedGeneration != 2) readLogResult.liveObjectTable.Preserve(rangeStart, rangeLength, lastTickIndex); } else { readLogResult.liveObjectTable.GenerationInterval(rangeStart, rangeLength, rangeGeneration, lastTickIndex); } } generationSize[rangeGeneration] += rangeLength; } if (startGC == 0 && readLogResult.liveObjectTable != null) { readLogResult.liveObjectTable.RecordGc(lastTickIndex, condemnedGeneration, readLogResult.sampleObjectTable, false); } break; case 'L': case 'l': { c = ReadChar(); int isCritical = ReadInt(); ulong objectId = ReadULong(); if (pos >= startFileOffset && pos < endFileOffset && readLogResult.liveObjectTable != null) { // try to find the allocation stack trace and allocation time // from the live object table LiveObjectTable.LiveObject liveObject; readLogResult.liveObjectTable.GetNextObject(objectId, objectId, out liveObject); if (liveObject.id == objectId) { if (isCritical != 0 && readLogResult.criticalFinalizerHistogram != null) readLogResult.criticalFinalizerHistogram.AddObject(liveObject.typeSizeStacktraceIndex, 1); if (readLogResult.finalizerHistogram != null) readLogResult.finalizerHistogram.AddObject(liveObject.typeSizeStacktraceIndex, 1); } } break; } case 'I': case 'i': c = ReadChar(); int tickCount = ReadInt(); if (c != -1) { lastTickIndex = AddTimePos(tickCount, lastLineStartPos); if (maxTickIndex < lastTickIndex) maxTickIndex = lastTickIndex; } break; case 'G': case 'g': c = ReadChar(); int gcGen0Count = ReadInt(); int gcGen1Count = ReadInt(); int gcGen2Count = ReadInt(); // if the newer 'b' lines occur, disregard the 'g' lines. if (gcCount[0] == 0 && readLogResult.liveObjectTable != null) { if (c == -1 || gcGen0Count < 0) readLogResult.liveObjectTable.RecordGc(lastTickIndex, 0, readLogResult.sampleObjectTable, gcGen0Count < 0); else readLogResult.liveObjectTable.RecordGc(lastTickIndex, gcGen0Count, gcGen1Count, gcGen2Count, readLogResult.sampleObjectTable); } break; case 'N': case 'n': { c = ReadChar(); int funcIndex; int stackTraceIndex = ReadInt(); stackPtr = 0; int flag = ReadInt(); int matched = flag / 4; int hadTypeId = (flag & 2); bool hasTypeId = (flag & 1) == 1; if (hasTypeId) { intStack[stackPtr++] = ReadInt(); intStack[stackPtr++] = ReadInt(); } if (matched > 0 && c != -1) { /* use some other stack trace as a reference */ int otherStackTraceId = ReadInt(); otherStackTraceId = stacktraceTable.MapTypeSizeStacktraceId(otherStackTraceId); int[] stacktrace = stacktraceTable.IndexToStacktrace(otherStackTraceId); if (matched > stacktrace.Length - hadTypeId) matched = stacktrace.Length - hadTypeId; for(int i = 0; i < matched; i++) { int funcId = stacktrace[i + hadTypeId]; Debug.Assert(funcId < funcName.Length && funcName[funcId] != null); intStack[stackPtr++] = funcId; if (stackPtr >= intStack.Length) { intStack = GrowIntVector(intStack); } } } while ((funcIndex = ReadInt()) >= 0) { intStack[stackPtr] = funcIndex; stackPtr++; if (stackPtr >= intStack.Length) intStack = GrowIntVector(intStack); } if (c != -1) { stacktraceTable.Add(stackTraceIndex, intStack, stackPtr, hasTypeId); } break; } case 'y': case 'Y': { c = ReadChar(); int threadid = ReadInt(); if(!assembliesJustLoaded.ContainsKey(threadid)) { assembliesJustLoaded[threadid] = new List<string>(); } /* int assemblyId = */ ReadInt(); while (c == ' ' || c == '\t') { c = ReadChar(); } sb.Length = 0; while (c > '\r') { sb.Append((char)c); c = ReadChar(); } string assemblyName = sb.ToString(); assembliesJustLoaded[threadid].Add(assemblyName); break; } case 'S': case 's': { c = ReadChar(); int stackTraceIndex = ReadInt(); int funcIndex; stackPtr = 0; while ((funcIndex = ReadInt()) >= 0) { intStack[stackPtr] = funcIndex; stackPtr++; if (stackPtr >= intStack.Length) intStack = GrowIntVector(intStack); } if (c != -1) { stacktraceTable.Add(stackTraceIndex, intStack, stackPtr, false); } break; } case 'Z': case 'z': { sb.Length = 0; c = ReadChar(); while (c == ' ' || c == '\t') c = ReadChar(); while (c > '\r') { sb.Append((char)c); c = ReadChar(); } if (c != -1) { lastTickIndex = AddTimePos(lastLineStartPos); if (maxTickIndex < lastTickIndex) maxTickIndex = lastTickIndex; commentEventList.AddEvent(lastTickIndex, sb.ToString()); } break; } case 'H': case 'h': { c = ReadChar(); int threadId = ReadInt(); ulong handleId = ReadULong(); ulong initialObjectId = ReadULong(); int stacktraceId = ReadInt(); if (c != -1) { if (readLogResult.handleHash != null) readLogResult.handleHash[handleId] = new HandleInfo(threadId, handleId, initialObjectId, lastTickIndex, stacktraceId); if (readLogResult.createdHandlesHistogram != null) readLogResult.createdHandlesHistogram.AddObject(stacktraceId, 1); } break; } case 'J': case 'j': { c = ReadChar(); int threadId = ReadInt(); ulong handleId = ReadULong(); int stacktraceId = ReadInt(); if (c != -1) { if (readLogResult.handleHash != null) { if (readLogResult.handleHash.ContainsKey(handleId)) readLogResult.handleHash.Remove(handleId); else { // Console.WriteLine("Non-existent handle {0:x} destroyed in line {1}", handleId, line); int[] stacktrace = stacktraceTable.IndexToStacktrace(stacktraceId); for (int i = stacktrace.Length; --i >= 0; ) { Console.WriteLine(" {0}", funcName[stacktrace[i]]); } } } if (readLogResult.destroyedHandlesHistogram != null) readLogResult.destroyedHandlesHistogram.AddObject(stacktraceId, 1); } break; } default: { // just ignore the unknown while(c != '\n' && c != '\r') { c = ReadChar(); } break; } } while (c == ' ' || c == '\t') c = ReadChar(); if (c == '\r') c = ReadChar(); if (c == '\n') { c = ReadChar(); line++; } } // readLogResult.functionList.ReportCallCountSizes(readLogResult.callstackHistogram); } // catch (Exception) // { // throw new Exception(string.Format("Bad format in log file {0} line {1}", fileName, line)); // throw; // } finally { progressForm.Visible = false; progressForm.Dispose(); if (r != null) r.Close(); } }
internal void ReadFile(long startFileOffset, long endFileOffset, ReadLogResult readLogResult) { ReadFile(startFileOffset, endFileOffset, readLogResult, -1); }
private LiveObjectTable GetLiveObjectTable() { int endTickIndex = lastTickIndex; if (selectedEndTickIndex != 0) { endTickIndex = selectedEndTickIndex; } ReadNewLog log = sampleObjectTable.readNewLog; long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again ReadLogResult readLogResult = new ReadLogResult(); readLogResult.liveObjectTable = new LiveObjectTable(log); log.ReadFile(0, endPos, readLogResult); return readLogResult.liveObjectTable; }
private void whoAllocatedMenuItem_Click(object sender, System.EventArgs e) { int startTickIndex = 0; int endTickIndex = lastTickIndex; if (selectedStartTickIndex != 0) { startTickIndex = selectedStartTickIndex; endTickIndex = selectedEndTickIndex; } Histogram histogram; string title; if (startTickIndex != 0 && startTickIndex == endTickIndex) { histogram = GetLiveHistogram(); title = string.Format("Allocation Graph for Objects at {0:f3} seconds", lastLog.TickIndexToTime(startTickIndex)); } else { ReadNewLog log = sampleObjectTable.readNewLog; long startPos = log.TickIndexToPos(startTickIndex); long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again ReadLogResult readLogResult = new ReadLogResult(); readLogResult.allocatedHistogram = new Histogram(log); log.ReadFile(startPos, endPos, readLogResult); histogram = readLogResult.allocatedHistogram; title = string.Format("Allocation Graph for Objects allocated between {0:f3} and {1:f3} seconds", lastLog.TickIndexToTime(startTickIndex), lastLog.TickIndexToTime(endTickIndex)); } Graph graph = histogram.BuildAllocationGraph(new FilterForm()); // And post it back to the main form - hardest part is to compute an appropriate title... GraphViewForm graphViewForm = new GraphViewForm(graph, title); graphViewForm.Visible = true; }
internal static void FinalizerReport(bool criticalFinalizers, string logFileName, string startMarker, string endMarker) { // first read the entire file ReadNewLog log = new ReadNewLog(logFileName, false); ReadLogResult entireLogResult = GetLogResult(log); log.ReadFile(0, long.MaxValue, entireLogResult); // if we were given a start or an end marker, we need to re-read a portion of the file. ReadLogResult logResult = entireLogResult; if (startMarker != null || endMarker != null) { int startTickIndex = 0; int endTickIndex = entireLogResult.sampleObjectTable.lastTickIndex; if (startMarker != null) startTickIndex = FindMarkerTickIndex(startMarker, log); if (endMarker != null) endTickIndex = FindMarkerTickIndex(endMarker, log); long startPos = log.TickIndexToPos(startTickIndex); long endPos = log.TickIndexToPos(endTickIndex); // Read the selected portion of the log again logResult = new ReadLogResult(); logResult.liveObjectTable = new LiveObjectTable(log); logResult.finalizerHistogram = new Histogram(log); logResult.criticalFinalizerHistogram = new Histogram(log); log.ReadFile(startPos, endPos, logResult); if (startMarker == null) startMarker = CommentRangeForm.startCommentString; if (endMarker == null) endMarker = CommentRangeForm.shutdownCommentString; Console.WriteLine("{0} summary for {1} Objects between {2} ({3} secs) and {4} ({5} secs)", criticalFinalizers ? "Critical Finalized" : "Finalized", logFileName, startMarker, log.TickIndexToTime(startTickIndex), endMarker, log.TickIndexToTime(endTickIndex)); } else Console.WriteLine("{0} summary for {1}", criticalFinalizers ? "Critical Finalized" : "Finalized", logFileName); // now we are ready to produce the allocation report from the allocation histogram WriteReport(criticalFinalizers ? logResult.criticalFinalizerHistogram : logResult.finalizerHistogram, ""); }