public void TestFinalizerQueueObjects() { using DataTarget dt = TestTargets.FinalizationQueue.LoadFullDump(); ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); Stats stats = GetStats(runtime.Heap, runtime.EnumerateFinalizerQueueObjectAddresses()); Assert.Equal(42, stats.A); Assert.Equal(0, stats.B); Assert.Equal(0, stats.C); }
public void ShowFinalizerQueue(ClrRuntime runtime) { var appDomain = runtime.AppDomains[0]; foreach (ulong obj in runtime.EnumerateFinalizerQueueObjectAddresses()) { var type = runtime.Heap.GetObjectType(obj); if (type == null) { continue; } ulong size = type.GetSize(obj); Console.WriteLine("{0,12:X} {1,8:n0} {2}", obj, size, type.Name); } Console.WriteLine(); }
public void TestFinalizerQueueObjects() { using (DataTarget dt = TestTargets.FinalizationQueue.LoadFullDump()) { ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); int targetObjectsCount = 0; foreach (ulong address in runtime.EnumerateFinalizerQueueObjectAddresses()) { ClrType type = runtime.Heap.GetObjectType(address); if (type.Name == "DieFastB") { targetObjectsCount++; } } Assert.Equal(13, targetObjectsCount); } }
private void InspectProcess(int pId) { using (DataTarget target = DataTarget.AttachToProcess(pId, 10000)) { ShowCLRRuntimeInformation(target); ClrRuntime runtime = target.ClrVersions.First().CreateRuntime(); LoadThreads(runtime); Dictionary <string, TypeEntry> types = new Dictionary <string, TypeEntry>(); Dictionary <string, StringInfor> stringCount = new Dictionary <string, StringInfor>(); ClrHeap heap = runtime.Heap; var finalizerQueueObjects = runtime.EnumerateFinalizerQueueObjectAddresses().ToList(); var pinnedObjects = runtime.EnumerateHandles().Where(h => h.IsPinned).Select(h => h.Object).ToList(); var blockingObjects = heap.EnumerateBlockingObjects().Select(x => x.Object).ToList(); //var blockingObjects = runtime.Threads.SelectMany(x => x.BlockingObjects).Select(x => x.Object).ToList(); foreach (ulong obj in heap.EnumerateObjects()) { ClrType type = heap.GetObjectType(obj); var size = type.GetSize(obj); var gen = heap.GetGeneration(obj); var isInFinalizerQueue = finalizerQueueObjects.Contains(obj); var isPinned = pinnedObjects.Contains(obj); var isBlocking = blockingObjects.Contains(obj); if (types.ContainsKey(type.Name)) { types[type.Name].Count++; types[type.Name].MinSize = Math.Min(types[type.Name].MinSize, size); types[type.Name].MaxSize = Math.Max(types[type.Name].MaxSize, size); types[type.Name].TotalSize += size; types[type.Name].Generation0 += gen == 0 ? 1 : 0; types[type.Name].Generation1 += gen == 1 ? 1 : 0; types[type.Name].Generation2 += gen == 2 ? 1 : 0; types[type.Name].FinalizerQueueCount += isInFinalizerQueue ? 1 : 0; types[type.Name].PinnedCount += isPinned ? 1 : 0; types[type.Name].BlockingCount += isBlocking ? 1 : 0; } else { types[type.Name] = new TypeEntry { Name = type.Name, Count = 1, MinSize = size, MaxSize = size, TotalSize = size, Generation0 = gen == 0 ? 1 : 0, Generation1 = gen == 1 ? 1 : 0, Generation2 = gen == 2 ? 1 : 0, FinalizerQueueCount = isInFinalizerQueue ? 1 : 0, PinnedCount = isPinned ? 1 : 0, BlockingCount = isBlocking ? 1 : 0, }; } if (type.IsString) { var text = (string)type.GetValue(obj); if (stringCount.ContainsKey(text)) { stringCount[text].Count++; stringCount[text].Generation0 += gen == 0 ? 1 : 0; stringCount[text].Generation1 += gen == 1 ? 1 : 0; stringCount[text].Generation2 += gen == 2 ? 1 : 0; } else { stringCount[text] = new StringInfor { Text = text, Count = 1, Generation0 = gen == 0 ? 1 : 0, Generation1 = gen == 1 ? 1 : 0, Generation2 = gen == 2 ? 1 : 0, }; } } } var sortOrder = heapObjectsGrid.SortOrder == SortOrder.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending; var sortCol = heapObjectsGrid.SortedColumn; int rowcount = 0; heapObjectsGrid.Rows.Clear(); foreach (var val in types.Where(x => x.Value.Count > 1)) { var infor = val.Value; DataGridViewRow gridrow = new DataGridViewRow(); gridrow.DefaultCellStyle.SelectionBackColor = Color.Black; if (rowcount % 2 > 0) { gridrow.DefaultCellStyle.BackColor = Color.AliceBlue; } rowcount++; DataGridViewTextBoxCell name = new DataGridViewTextBoxCell(); name.Value = infor.Name; gridrow.Cells.Add(name); DataGridViewTextBoxCell count = new DataGridViewTextBoxCell(); count.Style.Alignment = DataGridViewContentAlignment.BottomRight; count.Style.Format = "n0"; count.Value = infor.Count; gridrow.Cells.Add(count); DataGridViewTextBoxCell minSize = new DataGridViewTextBoxCell(); minSize.Style.Alignment = DataGridViewContentAlignment.BottomRight; minSize.Style.Format = "n0"; if (infor.MinSize >= 85000) { minSize.Style.ForeColor = Color.Orange; minSize.ToolTipText = "Large Object Heap"; } minSize.Value = infor.MinSize; gridrow.Cells.Add(minSize); DataGridViewTextBoxCell maxSize = new DataGridViewTextBoxCell(); maxSize.Style.Alignment = DataGridViewContentAlignment.BottomRight; maxSize.Style.Format = "n0"; if (infor.MaxSize >= 85000) { maxSize.Style.ForeColor = Color.Orange; maxSize.ToolTipText = "Large Object Heap"; } maxSize.Value = infor.MaxSize; gridrow.Cells.Add(maxSize); DataGridViewTextBoxCell totalSize = new DataGridViewTextBoxCell(); totalSize.Style.Alignment = DataGridViewContentAlignment.BottomRight; totalSize.Style.Format = "n0"; totalSize.Value = infor.TotalSize; gridrow.Cells.Add(totalSize); DataGridViewTextBoxCell generation0 = new DataGridViewTextBoxCell(); generation0.Value = infor.Generation0; generation0.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation0.Style.Format = "n0"; gridrow.Cells.Add(generation0); DataGridViewTextBoxCell generation1 = new DataGridViewTextBoxCell(); generation1.Value = infor.Generation1; generation1.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation1.Style.Format = "n0"; gridrow.Cells.Add(generation1); DataGridViewTextBoxCell generation2 = new DataGridViewTextBoxCell(); generation2.Value = infor.Generation2; generation2.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation2.Style.Format = "n0"; gridrow.Cells.Add(generation2); DataGridViewTextBoxCell finalizerQueue = new DataGridViewTextBoxCell(); finalizerQueue.Value = infor.FinalizerQueueCount; finalizerQueue.Style.Alignment = DataGridViewContentAlignment.BottomRight; finalizerQueue.Style.Format = "n0"; gridrow.Cells.Add(finalizerQueue); DataGridViewTextBoxCell pinned = new DataGridViewTextBoxCell(); pinned.Value = infor.PinnedCount; pinned.Style.Alignment = DataGridViewContentAlignment.BottomRight; pinned.Style.Format = "n0"; gridrow.Cells.Add(pinned); DataGridViewTextBoxCell blocking = new DataGridViewTextBoxCell(); blocking.Value = infor.BlockingCount; blocking.Style.Alignment = DataGridViewContentAlignment.BottomRight; blocking.Style.Format = "n0"; gridrow.Cells.Add(blocking); heapObjectsGrid.Rows.Add(gridrow); } heapObjectsGrid.Columns[1].HeaderCell.ToolTipText = $"Total: { types.Values.Sum(x => x.Count).ToString("N0")} objects"; heapObjectsGrid.Columns[4].HeaderCell.ToolTipText = $"Total: {types.Values.Sum(x => (long)x.TotalSize).ToString("N0")} bytes"; if (sortCol != null) { heapObjectsGrid.Sort(sortCol, sortOrder); } // Strings Grid View: rowcount = 0; stringsGrid.Rows.Clear(); foreach (var str in stringCount) { DataGridViewRow gridrow = new DataGridViewRow(); gridrow.DefaultCellStyle.SelectionBackColor = Color.Black; if (rowcount % 2 > 0) { gridrow.DefaultCellStyle.BackColor = Color.AliceBlue; } rowcount++; DataGridViewTextBoxCell name = new DataGridViewTextBoxCell(); name.Value = str.Key; gridrow.Cells.Add(name); DataGridViewTextBoxCell length = new DataGridViewTextBoxCell(); length.Style.Alignment = DataGridViewContentAlignment.BottomRight; length.Style.Format = "n0"; length.Value = str.Key.Length; gridrow.Cells.Add(length); DataGridViewTextBoxCell count = new DataGridViewTextBoxCell(); count.Style.Alignment = DataGridViewContentAlignment.BottomRight; count.Style.Format = "n0"; count.Value = str.Value.Count; gridrow.Cells.Add(count); DataGridViewTextBoxCell generation0 = new DataGridViewTextBoxCell(); generation0.Value = str.Value.Generation0; generation0.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation0.Style.Format = "n0"; gridrow.Cells.Add(generation0); DataGridViewTextBoxCell generation1 = new DataGridViewTextBoxCell(); generation1.Value = str.Value.Generation1; generation1.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation1.Style.Format = "n0"; gridrow.Cells.Add(generation1); DataGridViewTextBoxCell generation2 = new DataGridViewTextBoxCell(); generation2.Value = str.Value.Generation2; generation2.Style.Alignment = DataGridViewContentAlignment.BottomRight; generation2.Style.Format = "n0"; gridrow.Cells.Add(generation2); stringsGrid.Rows.Add(gridrow); } } }
/// <summary> /// Enumerates all objects currently on the finalizer queue. (Not finalizable objects, but objects /// which have been collected and will be imminently finalized.) /// </summary> /// <returns>IEnumerable<System.UInt64>.</returns> /// <inheritdoc /> /// <inheritdoc /> public IEnumerable <ulong> EnumerateFinalizerQueueObjectAddresses() => Runtime.EnumerateFinalizerQueueObjectAddresses();