void DrawRow(PaintEventArgs e, long objId, int depth) { if (objId == 0) { return; } var objInfo = heapshot.ObjectsInfoMap[objId]; int currentY = SpacingY + (RowHeight + SpacingY) * depth; var size = e.Graphics.MeasureString(Fonts.Sans(12), session.GetTypeName(objInfo.TypeId)); e.Graphics.FillRectangle(heapshot.Roots.ContainsKey(objId) ? Brushes.Red : Brushes.Yellow, 0, currentY, Math.Max(BubbleWidth, (int)size.Width) + 10, RowHeight); e.Graphics.DrawText(Fonts.Sans(12), Colors.Black, 5, currentY + 5, session.GetTypeName(objInfo.TypeId)); e.Graphics.DrawText(Fonts.Sans(12), Colors.Black, 5, currentY + 5 + 13, objInfo.ObjAddr.ToString()); }
void CreateTypesView() { foreach (var type in typesToObjectsListMap) { typesCollection.Add(Tuple.Create(type.Key, session.GetTypeName(type.Key), type.Value.Count)); } typesGrid = new GridView { DataStore = typesCollection }; typesGrid.AllowMultipleSelection = false; typesGrid.Columns.Add(new GridColumn { DataCell = new TextBoxCell { Binding = Binding.Delegate <Tuple <long, string, int>, string>(r => r.Item3.ToString()) }, HeaderText = "Objects #" }); typesGrid.Columns.Add(new GridColumn { DataCell = new TextBoxCell { Binding = Binding.Delegate <Tuple <long, string, int>, string>(r => r.Item2) }, HeaderText = "Type Name" }); typesGrid.SelectedRowsChanged += Grid_SelectedRowsChanged; }
public CompareHeapshotsTab(KrofilerSession session, Heapshot hs1, Heapshot hs2) { this.session = session; if (hs2.Id > hs1.Id) { newHeapshot = hs2; oldHeapshot = hs1; } else { newHeapshot = hs1; oldHeapshot = hs2; } var diff = new DiffHeap(oldHeapshot, newHeapshot); var newObjects = diff.NewObjects.GroupBy(addr => addr.TypeId).ToDictionary(d => d.Key, d => d.ToList()); var deleted = diff.DeletedObjects.GroupBy(addr => addr.TypeId).ToDictionary(d => d.Key, d => d.ToList()); var allObjectsInOldHs = oldHeapshot.TypesToObjectsListMap; var allObjectsInNewHs = newHeapshot.TypesToObjectsListMap; var hashTableAllTypes = new HashSet <long>(); foreach (var t in allObjectsInOldHs) { hashTableAllTypes.Add(t.Key); } foreach (var t in allObjectsInNewHs) { hashTableAllTypes.Add(t.Key); } foreach (var typeId in hashTableAllTypes) { typesCollection.Add(new TypeChangeInfo { TypeId = typeId, TypeName = session.GetTypeName(typeId), NewObjects = newObjects.ContainsKey(typeId) ? newObjects[typeId] : EmptyList, DeadObjects = deleted.ContainsKey(typeId) ? deleted[typeId] : EmptyList, OldHsObjects = allObjectsInOldHs.ContainsKey(typeId) ? allObjectsInOldHs[typeId] : EmptyList, NewHsObjects = allObjectsInNewHs.ContainsKey(typeId) ? allObjectsInNewHs[typeId] : EmptyList }); } filterTypesTextBox = new TextBox(); filterTypesTextBox.TextChanged += FilterTypesTextBox_TextChanged; CreateTypesView(); var filterAndTypesStackLayout = new StackLayout(); filterAndTypesStackLayout.Items.Add(new StackLayoutItem(filterTypesTextBox, HorizontalAlignment.Stretch)); filterAndTypesStackLayout.Items.Add(new StackLayoutItem(typesGrid, HorizontalAlignment.Stretch, true)); Content = filterAndTypesStackLayout; }
void OnObjectIdChanged() { stacktraceView.Items.Clear(); var sf = objectInfo.Allocation.Backtrace.Reverse().Select(b => session.GetMethodName(b)); foreach (var f in sf) { stacktraceView.Items.Add(f); } retentionList.Items.Clear(); if (heapshot.Roots.TryGetValue(objectInfo.ObjAddr, out var root)) { retentionList.Items.Add("Object is root itself:" + root); } else { var shortestPath = heapshot.GetShortestPathToRoot(objectInfo.ObjAddr); foreach (var edge in shortestPath) { var objInfo = heapshot.ObjectsInfoMap[edge.Source]; var typeName = session.GetTypeName(objInfo.TypeId); retentionList.Items.Add(new RetentionItem(typeName, objInfo)); //TODO: Add field to name } if (shortestPath.Any()) { if (heapshot.Roots.TryGetValue(shortestPath.Last().Source, out root)) { retentionList.Items.Add("Root info:" + root); } } else { retentionList.Items.Add("This is weird... Couldn't find path to root"); } } }
void OnObjectIdChanged() { stacktraceView.Items.Clear(); var sf = objectInfo.Allocation.Backtrace.Reverse().Select(b => session.GetMethodName(b)); foreach (var f in sf) { stacktraceView.Items.Add(f); } retentionPaths.Pages.Clear(); var pathsToRoot = heapshot.GetTop5PathsToRoots(objectInfo.ObjAddr); int i = 0; foreach (var path in pathsToRoot.OrderBy(p => p.Count())) { i++; var listBox = new ListBox(); listBox.MouseDoubleClick += (s, e) => { if (listBox.SelectedValue is RetentionItem ri) { var newTab = new ObjectListTab(session, heapshot, new Dictionary <long, List <ObjectInfo> >() { [ri.obj.TypeId] = new List <ObjectInfo>() { ri.obj } }); newTab.InsertTab += InsertTab; InsertTab(newTab, null); } }; var page = new TabPage(listBox) { Text = $"Path {i}" }; retentionPaths.Pages.Add(page); foreach (var edge in path) { var objInfo = heapshot.ObjectsInfoMap[edge.Target]; var typeName = session.GetTypeName(objInfo.TypeId); listBox.Items.Add(new RetentionItem(typeName, objInfo)); //TODO: Add field to name } listBox.Items.Add(new RetentionItem("Root:" + heapshot.Roots[path.Last().Target].Name, heapshot.ObjectsInfoMap[path.Last().Target])); } if (!pathsToRoot.Any()) { if (heapshot.Roots.TryGetValue(objectInfo.ObjAddr, out var root)) { AddSingleEntry("Object is root itself:" + root.Name); } else { AddSingleEntry("This is weird... Couldn't find path to root"); } } referencesList.Items.Clear(); foreach (var r in objectInfo.ReferencesTo) { var obj = heapshot.ObjectsInfoMap[r]; referencesList.Items.Add(new RetentionItem(session.GetTypeName(obj.TypeId) + ": " + r, obj)); } }