From 82859cd69090d8702c1cb96145f8f36da04df7e0 Mon Sep 17 00:00:00 2001 From: Massimiliano Mantione Date: Mon, 3 Nov 2008 09:56:25 +0000 Subject: Massive refactoring to unify allocations and heap objects inside heap analysis. svn path=/trunk/mono-tools/; revision=117728 --- Mono.Profiler/heap-snapshot-explorer/ChangeLog | 9 + .../heap-snapshot-explorer/HeapExplorerActions.cs | 2 +- .../HeapExplorerTreeModel.cs | 302 ++++++++++++--- .../heap-snapshot-explorer/HeapSnapshotExplorer.cs | 415 ++++++++++++++++----- .../heap-snapshot-explorer/LoadedClassChooser.cs | 6 +- .../heap-snapshot-explorer/gtk-gui/gui.stetic | 2 +- Mono.Profiler/heap-snapshot-viewer/ChangeLog | 4 + Mono.Profiler/heap-snapshot-viewer/Main.cs | 6 +- .../profiler-decoder-library/BaseTypes.cs | 30 +- Mono.Profiler/profiler-decoder-library/ChangeLog | 17 + Mono.Profiler/profiler-decoder-library/Decoder.cs | 13 +- .../profiler-decoder-library/EventProcessor.cs | 66 +++- .../profiler-decoder-library/ObjectModel.cs | 390 ++++++++++++++----- Mono.Profiler/profiler-decoder-library/Reader.cs | 8 +- Mono.Profiler/profiler-file-decoder/ChangeLog | 3 + Mono.Profiler/profiler-file-decoder/Main.cs | 12 +- 16 files changed, 1010 insertions(+), 275 deletions(-) (limited to 'Mono.Profiler') diff --git a/Mono.Profiler/heap-snapshot-explorer/ChangeLog b/Mono.Profiler/heap-snapshot-explorer/ChangeLog index 948f1f88..9a720d31 100644 --- a/Mono.Profiler/heap-snapshot-explorer/ChangeLog +++ b/Mono.Profiler/heap-snapshot-explorer/ChangeLog @@ -1,3 +1,12 @@ +2008-11-03 Massimiliano Mantione + * HeapExplorerTreeModel.cs: Massive refactory of "Node" class, making + it generic in terms of the node contents (HeapObject-AllocatedObject). + Moreover, made so that each node type can choose its own context menu. + * HeapSnapshotExplorer.cs: Likewise. + * LoadedClassChooser.cs: Likewise. + * HeapExplorerActions.cs: Likewise. + * gtk-gui/gui.stetic: Likewise. + 2008-10-13 Massimiliano Mantione * HeapExplorerTreeModel.cs: Use new HeapObject non-generic class. diff --git a/Mono.Profiler/heap-snapshot-explorer/HeapExplorerActions.cs b/Mono.Profiler/heap-snapshot-explorer/HeapExplorerActions.cs index e75fbe9e..a723b1da 100644 --- a/Mono.Profiler/heap-snapshot-explorer/HeapExplorerActions.cs +++ b/Mono.Profiler/heap-snapshot-explorer/HeapExplorerActions.cs @@ -28,7 +28,7 @@ namespace Mono.Profiler protected virtual void OnLoadData (object sender, System.EventArgs e) { - explorer.OnLoadData (); + explorer.OnLoadHeapSnapshotData (); } } } diff --git a/Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs b/Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs index a4be67ac..64277c9c 100644 --- a/Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs +++ b/Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs @@ -32,12 +32,33 @@ using Gtk; namespace Mono.Profiler { public class HeapExplorerTreeModel { - public abstract class Node { - public abstract HeapObjectSet Objects { - get; + public interface INode { + IHeapItemSet Items {get;} + string Description {get;} + TreeIter TreeIter {get;} + INode Parent {get;} + INode Root {get;} + string Count {get;} + string AllocatedBytes {get;} + Menu ContextMenu {get;} + } + public interface IRootNode : INode { + } + + public abstract class Node : INode where HI : IHeapItem { + public abstract HeapItemSet Items {get;} + IHeapItemSet INode.Items { + get { + return Items; + } } - public abstract string Description { - get; + + protected abstract SubSetNode NewSubSet (HeapItemSet items); + + public virtual string Description { + get { + return Items.ShortDescription; + } } protected HeapExplorerTreeModel model; @@ -48,14 +69,19 @@ namespace Mono.Profiler } } - Node parent; - public Node Parent { + Node parent; + public Node Parent { + get { + return parent; + } + } + INode INode.Parent { get { return parent; } } - public Node Root { + public Node Root { get { if (parent != null) { return parent.Root; @@ -64,11 +90,16 @@ namespace Mono.Profiler } } } + INode INode.Root { + get { + return Root; + } + } public string Count { get { - if (Objects != null) { - return Objects.HeapObjects.Length.ToString (); + if (Items != null) { + return Items.Elements.Length.ToString (); } else { return ""; } @@ -76,8 +107,8 @@ namespace Mono.Profiler } public string AllocatedBytes { get { - if (Objects != null) { - return Objects.AllocatedBytes.ToString (); + if (Items != null) { + return Items.AllocatedBytes.ToString (); } else { return ""; } @@ -94,28 +125,42 @@ namespace Mono.Profiler } } - public SubSetNode Filter (IHeapObjectFilter filter) { - HeapObjectSetFromFilter subSet = new HeapObjectSetFromFilter (Objects, filter); - SubSetNode result = new SubSetNode (model, this, subSet); + public SubSetNode Filter (IHeapItemFilter filter) { + HeapItemSetFromFilter subSet = new HeapItemSetFromFilter (Items, filter); + SubSetNode result = NewSubSet (subSet); return result; } - public static void PerformComparison (Node firstNode, Node secondNode, out SubSetNode onlyInFirstNode, out SubSetNode onlyInSecondNode) { - HeapObjectSet onlyInFirstSet; - HeapObjectSet onlyInSecondSet; - HeapObjectSetFromComparison.PerformComparison (firstNode.Objects, secondNode.Objects, out onlyInFirstSet, out onlyInSecondSet); - onlyInFirstNode = new SubSetNode (firstNode.model, firstNode, onlyInFirstSet); - onlyInSecondNode = new SubSetNode (secondNode.model, secondNode, onlyInSecondSet); + public void CompareWithNode (Node otherNode) where OHI : IHeapItem { + HeapItemSet onlyInThisSet; + HeapItemSet onlyInOtherSet; + Items.CompareWithSet (otherNode.Items, out onlyInThisSet, out onlyInOtherSet); + NewSubSet (onlyInThisSet); + otherNode.NewSubSet (onlyInOtherSet); + } + + public void IntersectWithNode (Node otherNode) where OHI : IHeapItem { + NewSubSet (Items.IntersectWithSet (otherNode.Items)); } - protected Node (HeapExplorerTreeModel model, Node parent) { + public void SelectObjectsReferencingItem (Node objectsNode) { + objectsNode.NewSubSet (Items.ObjectsReferencingItemInSet (objectsNode.Items)); + } + + public void SelectObjectsReferencedByItem (Node objectsNode) { + objectsNode.NewSubSet (Items.ObjectsReferencedByItemInSet (objectsNode.Items)); + } + + public abstract Menu ContextMenu {get;} + + protected Node (HeapExplorerTreeModel model, Node parent) { this.model = model; this.parent = parent; this.treeIter = HandleNodeCreation (); } } - public class SnapshotNode : Node { + public class SnapshotNode : Node, IRootNode { SeekableLogFileReader.Block heapBlock; HeapSnapshot snapshot; @@ -125,49 +170,185 @@ namespace Mono.Profiler } } - HeapObjectSetFromSnapshot objects; - public override HeapObjectSet Objects { + HeapObjectSetFromSnapshot items; + public override HeapItemSet Items { get { - return objects; + return items; } } public void ReadSnapshot () { - model.Reader.ReadBlock (heapBlock).Decode (model.heapEventProcessor, model.Reader); - snapshot = model.heapEventProcessor.LastHeapSnapshot; - objects = new HeapObjectSetFromSnapshot (snapshot); - model.Model.SetValue (TreeIter, 0, this); + if (items == null) { + model.heapEventProcessor.RecordAllocations = true; + model.Reader.ReadBlock (heapBlock).Decode (model.heapEventProcessor, model.Reader); + snapshot = model.heapEventProcessor.LastHeapSnapshot; + items = new HeapObjectSetFromSnapshot (snapshot); + model.Model.SetValue (TreeIter, 0, this); + } } public override string Description { get { - return heapBlock.TimeFromStart.ToString (); + if (items != null) { + return items.ShortDescription; + } else { + return String.Format ("Heap block ({0}.{1:000}s)", heapBlock.TimeFromStart.Seconds, heapBlock.TimeFromStart.Milliseconds); + } + } + } + + protected override SubSetNode NewSubSet (HeapItemSet items) { + return new HeapObjectSubSetNode (model, this, items); + } + + public override Menu ContextMenu { + get { + if (items != null) { + if (model.Explorer.NodeIsMarked) { + if (model.Explorer.MarkIsForComparison) { + return model.Explorer.CompareObjectSet; + } else if (model.Explorer.MarkIsForFiltering) { + return model.Explorer.FilterObjectSetUsingSelection; + } else { + throw new Exception ("Mark is buggy"); + } + } else { + return model.Explorer.FilterObjectSet; + } + } else { + return model.Explorer.LoadHeapSnapshotBlock; + } } } public SnapshotNode (HeapExplorerTreeModel model, SeekableLogFileReader.Block heapBlock) : base (model, null) { this.heapBlock = heapBlock; - this.objects = null; + this.items = null; this.snapshot = null; } } - public class SubSetNode : Node { - HeapObjectSet objects; - public override HeapObjectSet Objects { + public class AllocationsNode : Node, IRootNode { + SeekableLogFileReader.Block[] eventBlocks; + + AllocatedObjectSetFromEvents items; + public override HeapItemSet Items { get { - return objects; + return items; + } + } + + public void ReadEvents () { + if (items == null) { + model.heapEventProcessor.RecordAllocations = true; + foreach (SeekableLogFileReader.Block eventBlock in eventBlocks) { + model.Reader.ReadBlock (eventBlock).Decode (model.heapEventProcessor, model.Reader); + } + items = new AllocatedObjectSetFromEvents (eventBlocks [0].TimeFromStart, model.heapEventProcessor.AllocatedObjects); + model.Model.SetValue (TreeIter, 0, this); } } public override string Description { get { - return objects.ShortDescription; + if (items != null) { + return items.ShortDescription; + } else { + return String.Format ("Events ({0}.{1:000}s)", eventBlocks [0].TimeFromStart.Seconds, eventBlocks [0].TimeFromStart.Milliseconds); + } } } - public SubSetNode (HeapExplorerTreeModel model, Node parent, HeapObjectSet objects) : base (model, parent) { - this.objects = objects; + protected override SubSetNode NewSubSet (HeapItemSet items) { + return new AllocatedObjectSubSetNode (model, this, items); + } + + public override Menu ContextMenu { + get { + if (items != null) { + if (model.Explorer.NodeIsMarked) { + if (model.Explorer.MarkIsForComparison) { + return model.Explorer.CompareAllocationSet; + } else if (model.Explorer.MarkIsForFiltering) { + return model.Explorer.FilterAllocationSetUsingSelection; + } else { + throw new Exception ("Mark is buggy"); + } + } else { + return model.Explorer.FilterAllocationSet; + } + } else { + return model.Explorer.LoadAllocationsBlocks; + } + } + } + + public AllocationsNode (HeapExplorerTreeModel model, SeekableLogFileReader.Block[] eventBlocks) : base (model, null) { + this.eventBlocks = eventBlocks; + this.items = null; + } + } + + public abstract class SubSetNode : Node where HI : IHeapItem { + HeapItemSet items; + public override HeapItemSet Items { + get { + return items; + } + } + + protected SubSetNode (HeapExplorerTreeModel model, Node parent, HeapItemSet items) : base (model, parent) { + this.items = items; + } + } + + public class HeapObjectSubSetNode : SubSetNode { + protected override SubSetNode NewSubSet (HeapItemSet items) { + return new HeapObjectSubSetNode (model, this, items); + } + + public override Menu ContextMenu { + get { + if (model.Explorer.NodeIsMarked) { + if (model.Explorer.MarkIsForComparison) { + return model.Explorer.CompareObjectSet; + } else if (model.Explorer.MarkIsForFiltering) { + return model.Explorer.FilterObjectSetUsingSelection; + } else { + throw new Exception ("Mark is buggy"); + } + } else { + return model.Explorer.FilterObjectSet; + } + } + } + + public HeapObjectSubSetNode (HeapExplorerTreeModel model, Node parent, HeapItemSet items) : base (model, parent, items) { + } + } + + public class AllocatedObjectSubSetNode : SubSetNode { + protected override SubSetNode NewSubSet (HeapItemSet items) { + return new AllocatedObjectSubSetNode (model, this, items); + } + + public override Menu ContextMenu { + get { + if (model.Explorer.NodeIsMarked) { + if (model.Explorer.MarkIsForComparison) { + return model.Explorer.CompareAllocationSet; + } else if (model.Explorer.MarkIsForFiltering) { + return model.Explorer.FilterAllocationSetUsingSelection; + } else { + throw new Exception ("Mark is buggy"); + } + } else { + return model.Explorer.FilterAllocationSet; + } + } + } + + public AllocatedObjectSubSetNode (HeapExplorerTreeModel model, Node parent, HeapItemSet items) : base (model, parent, items) { } } @@ -207,35 +388,66 @@ namespace Mono.Profiler } protected HeapEventProcessor heapEventProcessor; - List rootNodes; - public SnapshotNode[] RootNodes { + List rootNodes; + public IRootNode[] RootNodes { get { return rootNodes.ToArray (); } } + HeapSnapshotExplorer explorer; + public HeapSnapshotExplorer Explorer { + get { + return explorer; + } + } + + AllocationsNode CreateAllocationsNode (List eventBlocks) { + AllocationsNode node; + if (eventBlocks.Count > 0) { + node = new AllocationsNode (this, eventBlocks.ToArray ()); + rootNodes.Add (node); + } else { + node = null; + } + eventBlocks.Clear (); + return node; + } + public void Initialize () { - Reset (); + List eventBlocks = new List (); + Reset (); foreach (SeekableLogFileReader.Block block in reader.Blocks) { if (block.Code == BlockCode.HEAP_DATA) { + CreateAllocationsNode (eventBlocks); SnapshotNode node = new SnapshotNode (this, block); rootNodes.Add (node); + } else if (block.Code == BlockCode.EVENTS) { + eventBlocks.Add (block); + } else if (block.Code == BlockCode.DIRECTIVES) { + reader.ReadBlock (block).Decode (heapEventProcessor, reader); } else if (block.Code == BlockCode.MAPPING) { reader.ReadBlock (block).Decode (heapEventProcessor, reader); + } else if (block.Code == BlockCode.INTRO) { + reader.ReadBlock (block).Decode (heapEventProcessor, reader); + } else if (block.Code == BlockCode.END) { + reader.ReadBlock (block).Decode (heapEventProcessor, reader); } } + CreateAllocationsNode (eventBlocks); } public void Reset () { model.Clear (); } - public HeapExplorerTreeModel (SeekableLogFileReader reader) { - model = new TreeStore (new Type [] {typeof (Node)}); + public HeapExplorerTreeModel (SeekableLogFileReader reader, HeapSnapshotExplorer explorer) { + model = new TreeStore (new Type [] {typeof (INode)}); heapEventProcessor = new HeapEventProcessor (); this.reader = reader; - rootNodes = new List (); + this.explorer = explorer; + rootNodes = new List (); } } } diff --git a/Mono.Profiler/heap-snapshot-explorer/HeapSnapshotExplorer.cs b/Mono.Profiler/heap-snapshot-explorer/HeapSnapshotExplorer.cs index 391cfb77..6d0ff0eb 100644 --- a/Mono.Profiler/heap-snapshot-explorer/HeapSnapshotExplorer.cs +++ b/Mono.Profiler/heap-snapshot-explorer/HeapSnapshotExplorer.cs @@ -22,12 +22,8 @@ namespace Mono.Profiler } } - Menu LoadBlock; - Menu FilterSet; - Menu CompareSet; - - HeapExplorerTreeModel.Node currentSelection; - public HeapExplorerTreeModel.Node CurrentSelection { + HeapExplorerTreeModel.INode currentSelection; + public HeapExplorerTreeModel.INode CurrentSelection { get { return currentSelection; } @@ -35,8 +31,8 @@ namespace Mono.Profiler [Gtk.TreeNode (ListOnly=true)] public class ClassStatisticsNode : Gtk.TreeNode { - HeapObjectSet.HeapObjectSetClassStatistics classStatistics; - public HeapObjectSet.HeapObjectSetClassStatistics ClassStatistics { + HeapItemSetClassStatistics classStatistics; + public HeapItemSetClassStatistics ClassStatistics { get { return classStatistics; } @@ -53,7 +49,7 @@ namespace Mono.Profiler } } - public ClassStatisticsNode (HeapObjectSet.HeapObjectSetClassStatistics classStatistics) { + public ClassStatisticsNode (HeapItemSetClassStatistics classStatistics) { this.classStatistics = classStatistics; } } @@ -70,59 +66,230 @@ namespace Mono.Profiler view.NodeStore = new Gtk.NodeStore (typeof (ClassStatisticsNode)); } - public static void FillTreeViewWithClassStatistics (NodeView view, HeapObjectSet.HeapObjectSetClassStatistics[] classes) { + public static void FillTreeViewWithClassStatistics (NodeView view, HeapItemSetClassStatistics[] classes) { view.NodeStore.Clear (); - foreach (HeapObjectSet.HeapObjectSetClassStatistics c in classes) { + foreach (HeapItemSetClassStatistics c in classes) { view.NodeStore.AddNode (new ClassStatisticsNode (c)); } } - HeapExplorerTreeModel.Node NodeSelectedForComparison; + HeapExplorerTreeModel.Node markedObjectNode; + public HeapExplorerTreeModel.Node MarkedObjectNode { + get { + return markedObjectNode; + } + } + HeapExplorerTreeModel.Node markedAllocationNode; + public HeapExplorerTreeModel.Node MarkedAllocationNode { + get { + return markedAllocationNode; + } + } + public bool NodeIsMarked { + get { + return (markedObjectNode != null) || (markedAllocationNode != null); + } + } + public HeapExplorerTreeModel.INode MarkedNode { + get { + return (markedObjectNode != null) ? (HeapExplorerTreeModel.INode) markedObjectNode : (markedAllocationNode != null) ? (HeapExplorerTreeModel.INode) markedAllocationNode : null; + } + } + bool markIsForComparison; + public bool MarkIsForComparison { + get { + return markIsForComparison; + } + } + bool markIsForFiltering; + public bool MarkIsForFiltering { + get { + return markIsForFiltering; + } + } + + Menu loadHeapSnapshotBlock; + public Menu LoadHeapSnapshotBlock { + get { + return loadHeapSnapshotBlock; + } + } + Menu loadAllocationsBlocks; + public Menu LoadAllocationsBlocks { + get { + return loadAllocationsBlocks; + } + } + Menu filterObjectSet; + public Menu FilterObjectSet { + get { + return filterObjectSet; + } + } + Menu filterAllocationSet; + public Menu FilterAllocationSet { + get { + return filterAllocationSet; + } + } + Menu compareObjectSet; + public Menu CompareObjectSet { + get { + return compareObjectSet; + } + } + Menu compareAllocationSet; + public Menu CompareAllocationSet { + get { + return compareAllocationSet; + } + } + Menu filterObjectSetUsingSelection; + public Menu FilterObjectSetUsingSelection { + get { + return filterObjectSetUsingSelection; + } + } + Menu filterAllocationSetUsingSelection; + public Menu FilterAllocationSetUsingSelection { + get { + return filterAllocationSetUsingSelection; + } + } public HeapSnapshotExplorer() { - this.Build(); + Build(); + MenuItem menuItem; - LoadBlock = new Menu (); - MenuItem loadData = new MenuItem ("Load block data"); - loadData.Activated += delegate { - OnLoadData (); + OnClearMark (); + + loadHeapSnapshotBlock = new Menu (); + menuItem = new MenuItem ("Load block data"); + menuItem.Activated += delegate { + OnLoadHeapSnapshotData (); + }; + loadHeapSnapshotBlock.Append (menuItem); + + loadAllocationsBlocks = new Menu (); + menuItem = new MenuItem ("Load block data"); + menuItem.Activated += delegate { + OnLoadAllocationsEventData (); }; - LoadBlock.Append (loadData); + loadAllocationsBlocks.Append (menuItem); - FilterSet = new Menu (); - MenuItem filterByClass = new MenuItem ("Filter by object class"); - filterByClass.Activated += delegate { - OnFilterByClass (); + filterObjectSet = new Menu (); + menuItem = new MenuItem ("Filter by object class"); + menuItem.Activated += delegate { + OnFilterByClass (); }; - FilterSet.Append (filterByClass); - MenuItem filterByReferencesObjectOfClass = new MenuItem ("Filter by \"references object of class\""); - filterByReferencesObjectOfClass.Activated += delegate { + filterObjectSet.Append (menuItem); + menuItem = new MenuItem ("Filter by \"references object of class\""); + menuItem.Activated += delegate { OnFilterByReferencesObjectOfClass (); }; - FilterSet.Append (filterByReferencesObjectOfClass); - MenuItem filterByIsReferencedByObjectOfClass = new MenuItem ("Filter by \"is referenced by object of class\""); - filterByIsReferencedByObjectOfClass.Activated += delegate { + filterObjectSet.Append (menuItem); + menuItem = new MenuItem ("Filter by \"is referenced by object of class\""); + menuItem.Activated += delegate { OnFilterByIsReferencedByObjectOfClass (); }; - FilterSet.Append (filterByIsReferencedByObjectOfClass); - MenuItem markSetForComparison = new MenuItem ("Mark set for comparison"); - markSetForComparison.Activated += delegate { - OnMarkSetForComparison (); + filterObjectSet.Append (menuItem); + menuItem = new MenuItem ("Mark set for comparison"); + menuItem.Activated += delegate { + OnMarkObjectSetForComparison (); + }; + filterObjectSet.Append (menuItem); + menuItem = new MenuItem ("Mark set for \"set reference\" filtering"); + menuItem.Activated += delegate { + OnMarkObjectSetForFiltering (); + }; + filterObjectSet.Append (menuItem); + + filterAllocationSet = new Menu (); + menuItem = new MenuItem ("Filter by object class"); + menuItem.Activated += delegate { + OnFilterByClass (); + }; + filterAllocationSet.Append (menuItem); + menuItem = new MenuItem ("Mark set for comparison"); + menuItem.Activated += delegate { + OnMarkAllocationSetForComparison (); + }; + filterAllocationSet.Append (menuItem); + // For now no set based filtering for allocations... + //menuItem = new MenuItem ("Mark set for filtering"); + //menuItem.Activated += delegate { + // OnMarkAllocationSetForFiltering (); + //}; + //filterAllocationSet.Append (menuItem); + + compareObjectSet = new Menu (); + menuItem = new MenuItem ("Perform comparison with this set"); + menuItem.Activated += delegate { + OnCompareWithSet (); + }; + compareObjectSet.Append (menuItem); + menuItem = new MenuItem ("Perform intersection with this set"); + menuItem.Activated += delegate { + OnIntersectWithSet (); + }; + compareObjectSet.Append (menuItem); + menuItem = new MenuItem ("Clear selection"); + menuItem.Activated += delegate { + OnClearMark (); }; - FilterSet.Append (markSetForComparison); + compareObjectSet.Append (menuItem); - CompareSet = new Menu (); - MenuItem performComparison = new MenuItem ("Perform comparison with this set"); - performComparison.Activated += delegate { - OnPerformComparison (); + compareAllocationSet = new Menu (); + menuItem = new MenuItem ("Perform comparison with this set"); + menuItem.Activated += delegate { + OnCompareWithSet (); }; - CompareSet.Append (performComparison); - MenuItem clearSetForComparison = new MenuItem ("Clear selection for comparison"); - clearSetForComparison.Activated += delegate { - OnClearSetForComparison (); + compareAllocationSet.Append (menuItem); + menuItem = new MenuItem ("Perform intersection with this set"); + menuItem.Activated += delegate { + OnIntersectWithSet (); }; - CompareSet.Append (clearSetForComparison); + compareAllocationSet.Append (menuItem); + menuItem = new MenuItem ("Clear selection"); + menuItem.Activated += delegate { + OnClearMark (); + }; + compareAllocationSet.Append (menuItem); + + filterObjectSetUsingSelection = new Menu (); + menuItem = new MenuItem ("Select objects referencing objects in this set"); + menuItem.Activated += delegate { + OnFilterByReferencesObjectInSet (); + }; + filterObjectSetUsingSelection.Append (menuItem); + menuItem = new MenuItem ("Select objects referenced by objects in this set"); + menuItem.Activated += delegate { + OnFilterByIsReferencedByObjectInSet (); + }; + filterObjectSetUsingSelection.Append (menuItem); + menuItem = new MenuItem ("Clear selection"); + menuItem.Activated += delegate { + OnClearMark (); + }; + filterObjectSetUsingSelection.Append (menuItem); + + filterAllocationSetUsingSelection = new Menu (); + menuItem = new MenuItem ("Select objects referencing objects in this set"); + menuItem.Activated += delegate { + OnFilterByReferencesObjectInSet (); + }; + filterAllocationSetUsingSelection.Append (menuItem); + menuItem = new MenuItem ("Select objects referenced by objects in this set"); + menuItem.Activated += delegate { + OnFilterByIsReferencedByObjectInSet (); + }; + filterAllocationSetUsingSelection.Append (menuItem); + menuItem = new MenuItem ("Clear selection"); + menuItem.Activated += delegate { + OnClearMark (); + }; + filterAllocationSetUsingSelection.Append (menuItem); PrepareTreeViewForClassStatistics (PerClassStatistics); @@ -130,10 +297,10 @@ namespace Mono.Profiler TreeSelection selection = (TreeSelection) o; TreeIter iter; if (selection.GetSelected (out iter)) { - currentSelection = (HeapExplorerTreeModel.Node) Tree.Model.GetValue (iter, 0); + currentSelection = (HeapExplorerTreeModel.INode) Tree.Model.GetValue (iter, 0); if (currentSelection != null) { - if (currentSelection.Objects != null) { - FillTreeViewWithClassStatistics (PerClassStatistics, currentSelection.Objects.ClassStatistics); + if (currentSelection.Items != null) { + FillTreeViewWithClassStatistics (PerClassStatistics, currentSelection.Items.ClassStatistics); } else { PerClassStatistics.NodeStore.Clear (); } @@ -155,30 +322,30 @@ namespace Mono.Profiler bytesColumn.PackStart (bytesCell, true); setColumn.SetCellDataFunc (setCell, delegate (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { - HeapExplorerTreeModel.Node node = (HeapExplorerTreeModel.Node) model.GetValue (iter, 0); + HeapExplorerTreeModel.INode node = (HeapExplorerTreeModel.INode) model.GetValue (iter, 0); CellRendererText textCell = (CellRendererText) cell; textCell.Markup = node.Description; - if (node != NodeSelectedForComparison) { + if (node != MarkedNode) { textCell.Style = Pango.Style.Normal; } else { textCell.Style = Pango.Style.Italic; } }); countColumn.SetCellDataFunc (countCell, delegate (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { - HeapExplorerTreeModel.Node node = (HeapExplorerTreeModel.Node) model.GetValue (iter, 0); + HeapExplorerTreeModel.INode node = (HeapExplorerTreeModel.INode) model.GetValue (iter, 0); CellRendererText textCell = (CellRendererText) cell; textCell.Markup = node.Count; - if (node != NodeSelectedForComparison) { + if (node != MarkedNode) { textCell.Style = Pango.Style.Normal; } else { textCell.Style = Pango.Style.Italic; } }); bytesColumn.SetCellDataFunc (bytesCell, delegate (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { - HeapExplorerTreeModel.Node node = (HeapExplorerTreeModel.Node) model.GetValue (iter, 0); + HeapExplorerTreeModel.INode node = (HeapExplorerTreeModel.INode) model.GetValue (iter, 0); CellRendererText textCell = (CellRendererText) cell; textCell.Markup = node.AllocatedBytes; - if (node != NodeSelectedForComparison) { + if (node != MarkedNode) { textCell.Style = Pango.Style.Normal; } else { textCell.Style = Pango.Style.Italic; @@ -193,88 +360,144 @@ namespace Mono.Profiler Tree.AppendColumn (countColumn); Tree.AppendColumn (bytesColumn); - LoadBlock.ShowAll (); - FilterSet.ShowAll (); - CompareSet.ShowAll (); - - NodeSelectedForComparison = null; + loadHeapSnapshotBlock.ShowAll (); + loadAllocationsBlocks.ShowAll (); + filterObjectSet.ShowAll (); + filterAllocationSet.ShowAll (); + compareObjectSet.ShowAll (); + compareAllocationSet.ShowAll (); + filterObjectSetUsingSelection.ShowAll (); + filterAllocationSetUsingSelection.ShowAll (); } - public void OnLoadData () { - if (CurrentSelection != null) { - HeapExplorerTreeModel.SnapshotNode snapshotNode = CurrentSelection as HeapExplorerTreeModel.SnapshotNode; - if ((snapshotNode != null) && (snapshotNode.Objects == null)) { - ((HeapExplorerTreeModel.SnapshotNode)CurrentSelection).ReadSnapshot (); - } + public void OnLoadHeapSnapshotData () { + HeapExplorerTreeModel.SnapshotNode node = CurrentSelection as HeapExplorerTreeModel.SnapshotNode; + if ((node != null) && (node.Items == null)) { + node.ReadSnapshot (); } } - public void OnFilterByClass () { - if (CurrentSelection != null) { - LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Objects.ClassStatistics); + public void OnLoadAllocationsEventData () { + HeapExplorerTreeModel.AllocationsNode node = CurrentSelection as HeapExplorerTreeModel.AllocationsNode; + if ((node != null) && (node.Items == null)) { + node.ReadEvents (); + } + } + + public void OnFilterByClass () where HI : IHeapItem { + HeapExplorerTreeModel.Node node = CurrentSelection as HeapExplorerTreeModel.Node; + if (node != null) { + LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Items.ClassStatistics); if (c != null) { - IHeapObjectFilter filter = new HeapObjectIsOfClass (c); - CurrentSelection.Filter (filter); + HeapItemIsOfClass filter = new HeapItemIsOfClass (c); + node.Filter (filter); } } } public void OnFilterByReferencesObjectOfClass () { - if (CurrentSelection != null) { - LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Root.Objects.ClassStatistics); + HeapExplorerTreeModel.Node node = CurrentSelection as HeapExplorerTreeModel.Node; + if (node!= null) { + LoadedClass c = LoadedClassChooser.ChooseClass (node.Root.Items.ClassStatistics); if (c != null) { - IHeapObjectFilter filter = new HeapObjectReferencesObjectOfClass (c); - CurrentSelection.Filter (filter); + HeapObjectReferencesObjectOfClass filter = new HeapObjectReferencesObjectOfClass (c); + node.Filter (filter); } } } public void OnFilterByIsReferencedByObjectOfClass () { - if (CurrentSelection != null) { - LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Root.Objects.ClassStatistics); + HeapExplorerTreeModel.Node node = CurrentSelection as HeapExplorerTreeModel.Node; + if (node != null) { + LoadedClass c = LoadedClassChooser.ChooseClass (node.Root.Items.ClassStatistics); if (c != null) { IHeapObjectFilter filter = new HeapObjectIsReferencedByObjectOfClass (c); - CurrentSelection.Filter (filter); + node.Filter (filter); } } } - public void OnMarkSetForComparison () { - if (CurrentSelection != null) { - NodeSelectedForComparison = CurrentSelection; - } + public void OnMarkObjectSetForComparison () { + markedObjectNode = CurrentSelection as HeapExplorerTreeModel.Node; + markedAllocationNode = null; + markIsForComparison = true; + markIsForFiltering = false; + } + + public void OnMarkObjectSetForFiltering () { + markedObjectNode = CurrentSelection as HeapExplorerTreeModel.Node; + markedAllocationNode = null; + markIsForComparison = false; + markIsForFiltering = true; } - public void OnClearSetForComparison () { - NodeSelectedForComparison = null; + public void OnMarkAllocationSetForComparison () { + markedObjectNode = null; + markedAllocationNode = CurrentSelection as HeapExplorerTreeModel.Node; + markIsForComparison = true; + markIsForFiltering = false; } - public void OnPerformComparison () { - if (CurrentSelection != null) { - HeapExplorerTreeModel.SubSetNode firstSubNode; - HeapExplorerTreeModel.SubSetNode secondSubNode; - HeapExplorerTreeModel.Node.PerformComparison (NodeSelectedForComparison, CurrentSelection, out firstSubNode, out secondSubNode); - NodeSelectedForComparison = null; + public void OnMarkAllocationSetForFiltering () { + markedObjectNode = null; + markedAllocationNode = CurrentSelection as HeapExplorerTreeModel.Node; + markIsForComparison = false; + markIsForFiltering = true; + } + + public void OnClearMark () { + markedObjectNode = null; + markedAllocationNode = null; + markIsForComparison = false; + markIsForFiltering = false; + } + + public void OnCompareWithSet () where HI : IHeapItem { + HeapExplorerTreeModel.Node node = CurrentSelection as HeapExplorerTreeModel.Node; + if (node != null) { + if (markedObjectNode != null) { + node.CompareWithNode (markedObjectNode); + } else if (markedAllocationNode != null) { + node.CompareWithNode (markedAllocationNode); + } + OnClearMark (); } } + public void OnIntersectWithSet () where HI : IHeapItem { + HeapExplorerTreeModel.Node node = CurrentSelection as HeapExplorerTreeModel.Node; + if (node != null) { + if (markedObjectNode != null) { + markedObjectNode.IntersectWithNode (node); + } else if (markedAllocationNode != null) { + markedAllocationNode.IntersectWithNode (node); + } + OnClearMark (); + } + } + + public void OnFilterByReferencesObjectInSet () where HI : IHeapItem { + HeapExplorerTreeModel.Node itemNode = CurrentSelection as HeapExplorerTreeModel.Node; + if ((itemNode != null) && (markedObjectNode != null)) { + itemNode.SelectObjectsReferencingItem (markedObjectNode); + OnClearMark (); + } + } + public void OnFilterByIsReferencedByObjectInSet () where HI : IHeapItem { + HeapExplorerTreeModel.Node itemNode = CurrentSelection as HeapExplorerTreeModel.Node; + if ((itemNode != null) && (markedObjectNode != null)) { + itemNode.SelectObjectsReferencedByItem (markedObjectNode); + OnClearMark (); + } + } [GLib.ConnectBefore] protected virtual void OnTreeButtonPress (object o, Gtk.ButtonPressEventArgs args) { if (args.Event.Button == 3) { if (CurrentSelection != null) { - HeapExplorerTreeModel.SnapshotNode snapshotNode = CurrentSelection as HeapExplorerTreeModel.SnapshotNode; - if ((snapshotNode != null) && (snapshotNode.Objects == null)) { - LoadBlock.Popup (); - } else { - if (NodeSelectedForComparison == null) { - FilterSet.Popup (); - } else if (CurrentSelection != NodeSelectedForComparison) { - CompareSet.Popup (); - } - } + CurrentSelection.ContextMenu.Popup (); } } } diff --git a/Mono.Profiler/heap-snapshot-explorer/LoadedClassChooser.cs b/Mono.Profiler/heap-snapshot-explorer/LoadedClassChooser.cs index 1124f85d..764885a1 100644 --- a/Mono.Profiler/heap-snapshot-explorer/LoadedClassChooser.cs +++ b/Mono.Profiler/heap-snapshot-explorer/LoadedClassChooser.cs @@ -18,7 +18,7 @@ namespace Mono.Profiler } } - HeapObjectSet.HeapObjectSetClassStatistics currentSelection; + HeapItemSetClassStatistics currentSelection; LoadedClassChooser() { @@ -38,7 +38,7 @@ namespace Mono.Profiler } } - void FillList (HeapObjectSet.HeapObjectSetClassStatistics[] classes) { + void FillList (HeapItemSetClassStatistics[] classes) { HeapSnapshotExplorer.FillTreeViewWithClassStatistics (ClassList, classes); currentSelection = null; } @@ -59,7 +59,7 @@ namespace Mono.Profiler static LoadedClassChooser chooser; - public static LoadedClass ChooseClass (HeapObjectSet.HeapObjectSetClassStatistics[] classes) { + public static LoadedClass ChooseClass (HeapItemSetClassStatistics[] classes) { LoadedClass result; if (chooser == null) { chooser = new LoadedClassChooser (); diff --git a/Mono.Profiler/heap-snapshot-explorer/gtk-gui/gui.stetic b/Mono.Profiler/heap-snapshot-explorer/gtk-gui/gui.stetic index da123d2b..014db4ec 100644 --- a/Mono.Profiler/heap-snapshot-explorer/gtk-gui/gui.stetic +++ b/Mono.Profiler/heap-snapshot-explorer/gtk-gui/gui.stetic @@ -5,7 +5,7 @@ 2.12.1 - + diff --git a/Mono.Profiler/heap-snapshot-viewer/ChangeLog b/Mono.Profiler/heap-snapshot-viewer/ChangeLog index 07e9014f..90bdbe66 100644 --- a/Mono.Profiler/heap-snapshot-viewer/ChangeLog +++ b/Mono.Profiler/heap-snapshot-viewer/ChangeLog @@ -1,3 +1,7 @@ +2008-11-03 Massimiliano Mantione + * Main.cs: Added "explorer" parameter to the model constructor, and + removed debugging code. + 2008-08-20 Massimiliano Mantione * Main.cs: Fix warning. * gtk-gui/gui.stetic: regenerated with correct pathnames. diff --git a/Mono.Profiler/heap-snapshot-viewer/Main.cs b/Mono.Profiler/heap-snapshot-viewer/Main.cs index 28858a03..3d7238d6 100644 --- a/Mono.Profiler/heap-snapshot-viewer/Main.cs +++ b/Mono.Profiler/heap-snapshot-viewer/Main.cs @@ -49,15 +49,11 @@ namespace Mono.Profiler return; } - foreach (SeekableLogFileReader.Block block in reader.Blocks) { - Console.WriteLine ("Found block {0} at offset {1} (length {2}, time from start {3})", block.Code, block.FileOffset, block.Length, block.TimeFromStart); - } - Application.Init (); MainWindow win = new MainWindow (); win.Show (); - win.HeapExplorer.Model = new HeapExplorerTreeModel (reader); + win.HeapExplorer.Model = new HeapExplorerTreeModel (reader, win.HeapExplorer); win.HeapExplorer.Model.Initialize (); Application.Run (); diff --git a/Mono.Profiler/profiler-decoder-library/BaseTypes.cs b/Mono.Profiler/profiler-decoder-library/BaseTypes.cs index 4f91f785..3de31bbd 100644 --- a/Mono.Profiler/profiler-decoder-library/BaseTypes.cs +++ b/Mono.Profiler/profiler-decoder-library/BaseTypes.cs @@ -93,6 +93,7 @@ namespace Mono.Profiler { DateTime StartTime {get;} ulong EndCounter {get;} DateTime EndTime {get;} + TimeSpan HeaderStartTime {get;} HO NewHeapObject (ulong id, LC c, uint size, ulong[] referenceIds, int referencesCount); HO GetHeapObject (ulong id); HO[] HeapObjects {get;} @@ -104,7 +105,7 @@ namespace Mono.Profiler { LM NewMethod (uint id, LC c, string name); MR NewExecutableMemoryRegion (uint id, string fileName, uint fileOffset, ulong startAddress, ulong endAddress); UFI NewUnmanagedFunction (uint id, string name, MR region); - HS NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, LC[] initialAllocations, bool recordSnapshot); + HS NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, TimeSpan headerStartTime, LC[] initialAllocations, bool recordSnapshot); bool RecordHeapSnapshots {get; set;} } @@ -126,6 +127,8 @@ namespace Mono.Profiler { DirectivesHandler Directives {get;} EH LoadedElements {get;} + Double TicksPerCounterUnit {get;} + TimeSpan ClicksToTimeSpan (ulong clicks); void Start (uint version, string runtimeFile, ProfilerFlags flags, ulong startCounter, DateTime startTime); void End (uint version, ulong endCounter, DateTime endTime); @@ -390,7 +393,7 @@ namespace Mono.Profiler { backReferences = new HO [backReferencesCounter]; backReferencesCounter = 0; } else { - references = emptyReferences; + backReferences = emptyReferences; } } internal void AddBackReference (HO heapObject) { @@ -444,7 +447,13 @@ namespace Mono.Profiler { return endTime; } } - + TimeSpan headerStartTime; + public TimeSpan HeaderStartTime { + get { + return headerStartTime; + } + } + public HO NewHeapObject (ulong id, LC c, uint size, ulong[] referenceIds, int referencesCount) { if (backReferencesInitialized) { throw new Exception ("Cannot create heap objects after backReferencesInitialized is true"); @@ -528,13 +537,14 @@ namespace Mono.Profiler { } } - public BaseHeapSnapshot (HeapObjectFactory heapObjectFactory, uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, bool recordSnapshot) { + public BaseHeapSnapshot (HeapObjectFactory heapObjectFactory, uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, TimeSpan headerStartTime, bool recordSnapshot) { this.heapObjectFactory = heapObjectFactory; this.collection = collection; this.startCounter = startCounter; this.startTime = startTime; this.endCounter = endCounter; this.endTime = endTime; + this.headerStartTime = headerStartTime; this.recordSnapshot = recordSnapshot; heap = new Dictionary (); backReferencesInitialized = false; @@ -711,6 +721,14 @@ namespace Mono.Profiler { return loadedElements; } } + public virtual Double TicksPerCounterUnit { + get { + return 0; + } + } + public virtual TimeSpan ClicksToTimeSpan (ulong clicks) { + return TimeSpan.FromTicks (0); + } public BaseProfilerEventHandler (EH loadedElements) { this.loadedElements = loadedElements; @@ -1212,8 +1230,8 @@ namespace Mono.Profiler { } List heapSnapshots; - public HS NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, LC[] initialAllocations, bool recordSnapshot) { - HS result = factory.NewHeapSnapshot (collection, startCounter, startTime, endCounter, endTime, initialAllocations, recordSnapshot); + public HS NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, TimeSpan headerStartTime, LC[] initialAllocations, bool recordSnapshot) { + HS result = factory.NewHeapSnapshot (collection, startCounter, startTime, endCounter, endTime, headerStartTime, initialAllocations, recordSnapshot); heapSnapshots.Add (result); return result; } diff --git a/Mono.Profiler/profiler-decoder-library/ChangeLog b/Mono.Profiler/profiler-decoder-library/ChangeLog index 035295c3..e33ea755 100644 --- a/Mono.Profiler/profiler-decoder-library/ChangeLog +++ b/Mono.Profiler/profiler-decoder-library/ChangeLog @@ -1,3 +1,20 @@ +2008-11-03 Massimiliano Mantione + * BaseTypes.cs: Added "header start time" property to the event + handler, so that there is always a "context" of when the event block + happened diring the execution. Added also this time as a parameter to + the heap snapshot factory and constructor. + * Decoder.cs: Likewise. + * Reader.cs: Likewise. + * EventProcessor.cs: Likewise. Moreover, fixed case of public + properties and added ability to record each allocation individually + (up to now the data was only aggregated, see "AllocatedObject"). + * ObjectModel.cs: Massive refactory of "HeapObjectSet", making it + generic so that it can be a set of IHeapItem (which in turn can be a + HeapObject or an AllocatedObject). + This enables exploring heap snapshots and relating each objectg to its + allocation event. + Also added filtering based on "references objects in another set". + 2008-10-13 Massimiliano Mantione * BaseTypes.cs: Turn HeapObject class into generic BaseHeapObject class, and add a new IAllocatedObject interface (this will give more freedom diff --git a/Mono.Profiler/profiler-decoder-library/Decoder.cs b/Mono.Profiler/profiler-decoder-library/Decoder.cs index 915d7f68..5880f4d5 100644 --- a/Mono.Profiler/profiler-decoder-library/Decoder.cs +++ b/Mono.Profiler/profiler-decoder-library/Decoder.cs @@ -131,6 +131,14 @@ namespace Mono.Profiler { return length; } } + ulong headerStartCounter; + public ulong HeaderStartCounter { + get { + return headerStartCounter; + } + } + + byte[] data; public byte Data (uint index) { @@ -858,7 +866,7 @@ namespace Mono.Profiler { ulong jobEndTime = ReadUlong (ref offsetInBlock); uint collection = ReadUint (ref offsetInBlock); - HS snapshot = handler.LoadedElements.NewHeapSnapshot (collection, jobStartCounter, microsecondsFromEpochToDateTime (jobStartTime), jobEndCounter, microsecondsFromEpochToDateTime (jobEndTime), handler.LoadedElements.Classes, handler.LoadedElements.RecordHeapSnapshots); + HS snapshot = handler.LoadedElements.NewHeapSnapshot (collection, jobStartCounter, microsecondsFromEpochToDateTime (jobStartTime), jobEndCounter, microsecondsFromEpochToDateTime (jobEndTime), handler.ClicksToTimeSpan (headerStartCounter), handler.LoadedElements.Classes, handler.LoadedElements.RecordHeapSnapshots); handler.HeapReportStart (snapshot); handler.DataProcessed (offsetInBlock); @@ -1066,10 +1074,11 @@ namespace Mono.Profiler { output.WriteLine (); } - public BlockData (uint fileOffset, BlockCode code, int length, byte[] data) { + public BlockData (uint fileOffset, BlockCode code, int length, ulong headerStartCounter, byte[] data) { this.fileOffset = fileOffset; this.code = code; this.length = length; + this.headerStartCounter = headerStartCounter; this.data = data; } } diff --git a/Mono.Profiler/profiler-decoder-library/EventProcessor.cs b/Mono.Profiler/profiler-decoder-library/EventProcessor.cs index 12e16e51..8820b1ce 100644 --- a/Mono.Profiler/profiler-decoder-library/EventProcessor.cs +++ b/Mono.Profiler/profiler-decoder-library/EventProcessor.cs @@ -139,28 +139,67 @@ namespace Mono.Profiler { } double ticksPerCounterUnit; - void updateTicksPerCounterUnit () { + public override Double TicksPerCounterUnit { + get { + return ticksPerCounterUnit; + } + } + void UpdateTicksPerCounterUnit () { if (currentCounter > startCounter) { ulong counterSpan = currentCounter - startCounter; TimeSpan timeSpan = currentTime - startTime; ticksPerCounterUnit = ((double)timeSpan.Ticks) / ((double)counterSpan); } } - void updateCounterAndTime (ulong currentCounter, DateTime currentTime) { + void UpdateCounterAndTime (ulong currentCounter, DateTime currentTime) { this.currentCounter = currentCounter; this.currentTime = currentTime; - updateTicksPerCounterUnit (); + UpdateTicksPerCounterUnit (); } - public DateTime counterToDateTime (ulong counter) { + public DateTime CounterToDateTime (ulong counter) { return StartTime + TimeSpan.FromTicks ((long) (ticksPerCounterUnit * (double)(counter - StartCounter))); } - public TimeSpan clicksToTimeSpan (ulong clicks) { + public override TimeSpan ClicksToTimeSpan (ulong clicks) { return TimeSpan.FromTicks ((long) (ticksPerCounterUnit * (double)clicks)); } - public double clicksToSeconds (ulong clicks) { + public double ClicksToSeconds (ulong clicks) { return (ticksPerCounterUnit * (double)clicks) / TimeSpan.TicksPerSecond; } + List allocatedObjects = null; + public bool RecordAllocations { + get { + return allocatedObjects != null; + } + set { + if (value) { + if (allocatedObjects != null) { + allocatedObjects.Clear (); + } else { + allocatedObjects = new List (); + } + } else { + allocatedObjects = null; + } + } + } + public AllocatedObject[] AllocatedObjects { + get { + if (RecordAllocations) { + AllocatedObject[] result = allocatedObjects.ToArray (); + allocatedObjects.Clear (); + return result; + } else { + return null; + } + } + } + protected void RecordAllocation (LoadedClass c, ulong objectId, uint size, LoadedMethod caller, bool jitTime, StackTrace trace) { + if (RecordAllocations) { + allocatedObjects.Add (new AllocatedObject (objectId, c, size, caller, jitTime, trace)); + } + } + public override void Start (uint version, string runtimeFile, ProfilerFlags flags, ulong startCounter, DateTime startTime) { this.version = version; this.runtimeFile = runtimeFile; @@ -175,15 +214,15 @@ namespace Mono.Profiler { } this.endCounter = endCounter; this.endTime = endTime; - updateCounterAndTime (endCounter, endTime); + UpdateCounterAndTime (endCounter, endTime); } public override void StartBlock (ulong startCounter, DateTime startTime, ulong threadId) { - updateCounterAndTime (startCounter, startTime); + UpdateCounterAndTime (startCounter, startTime); } public override void EndBlock (ulong endCounter, DateTime endTime, ulong threadId) { - updateCounterAndTime (endCounter, endTime); + UpdateCounterAndTime (endCounter, endTime); } public override void ModuleLoaded (ulong threadId, ulong startCounter, ulong endCounter, string name, bool success) {} @@ -223,6 +262,7 @@ namespace Mono.Profiler { } } c.InstanceCreated (size, caller, jitTime, trace); + RecordAllocation (c, objectId, size, caller, jitTime, trace); } public override void Exception (LoadedClass c, ulong counter) {} @@ -427,22 +467,22 @@ namespace Mono.Profiler { public double Start { get { - return data.clicksToSeconds (startCounter - data.StartCounter); + return data.ClicksToSeconds (startCounter - data.StartCounter); } } public double Duration { get { - return data.clicksToSeconds (endCounter - startCounter); + return data.ClicksToSeconds (endCounter - startCounter); } } public double MarkDuration { get { - return data.clicksToSeconds (markEndCounter - markStartCounter); + return data.ClicksToSeconds (markEndCounter - markStartCounter); } } public double SweepDuration { get { - return data.clicksToSeconds (sweepEndCounter - sweepStartCounter); + return data.ClicksToSeconds (sweepEndCounter - sweepStartCounter); } } diff --git a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs index fa2591e4..1a6d6b20 100644 --- a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs +++ b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs @@ -908,10 +908,61 @@ namespace Mono.Profiler { } } - public class HeapObject : BaseHeapObject { + public interface IHeapItem : IAllocatedObject { + } + + public class HeapObject : BaseHeapObject, IHeapItem { public HeapObject (ulong ID) : base (ID) {} } + public class AllocatedObject : IHeapItem { + ulong id; + public ulong ID { + get { + return id; + } + } + LoadedClass c; + public LoadedClass Class { + get { + return c; + } + } + uint size; + public uint Size { + get { + return size; + } + } + LoadedMethod caller; + public LoadedMethod Caller { + get { + return caller; + } + } + bool jitTime; + public bool JitTime { + get { + return jitTime; + } + } + StackTrace trace; + public StackTrace Trace { + get { + return trace; + } + } + + public AllocatedObject (ulong id, LoadedClass c, uint size, LoadedMethod caller, bool jitTime, StackTrace trace) { + this.id = id; + this.c = c; + this.size = size; + this.caller = caller; + this.jitTime = jitTime; + this.trace = trace; + } + } + public class HeapSnapshot : BaseHeapSnapshot { public class AllocationStatisticsPerClass { LoadedClass c; @@ -978,7 +1029,7 @@ namespace Mono.Profiler { statisticsPerClass.BytesFreed (size); } - public HeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, LoadedClass[] initialAllocations, bool recordSnapshot) : base (delegate (ulong ID) {return new HeapObject (ID);}, collection, startCounter, startTime, endCounter, endTime, recordSnapshot) { + public HeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, TimeSpan headerStartTime, LoadedClass[] initialAllocations, bool recordSnapshot) : base (delegate (ulong ID) {return new HeapObject (ID);}, collection, startCounter, startTime, endCounter, endTime, headerStartTime, recordSnapshot) { uint maxClassId = 0; foreach (LoadedClass c in initialAllocations) { if (c.ID > maxClassId) { @@ -993,14 +1044,18 @@ namespace Mono.Profiler { } } - public interface IHeapObjectFilter { + public interface IHeapItemFilter where HI : IHeapItem { string Description { get; } - bool Filter (HeapObject heapObject); + bool Filter (HI heapItem); + } + public interface IAllocatedObjectFilter : IHeapItemFilter { + } + public interface IHeapObjectFilter : IHeapItemFilter { } - public abstract class FilterHeapObjectByClass : IHeapObjectFilter { + public abstract class FilterHeapItemByClass : IHeapItemFilter where HI : IHeapItem { protected LoadedClass c; public LoadedClass Class { get { @@ -1008,7 +1063,7 @@ namespace Mono.Profiler { } } - public abstract bool Filter (HeapObject heapObject); + public abstract bool Filter (HI heapItem); string description; public string Description { @@ -1017,22 +1072,37 @@ namespace Mono.Profiler { } } - protected FilterHeapObjectByClass (LoadedClass c, string description) { + protected FilterHeapItemByClass (LoadedClass c, string description) { this.c = c; this.description = description; } } - - public class HeapObjectIsOfClass : FilterHeapObjectByClass { - static string BuildDescription (LoadedClass c) { + + public class HeapItemIsOfClass : FilterHeapItemByClass where HI : IHeapItem { + protected static string BuildDescription (LoadedClass c) { return String.Format ("Object has class {0}", c.Name); } - public override bool Filter (HeapObject heapObject) { - return heapObject.Class == c; + public override bool Filter (HI heapItem) { + return heapItem.Class == c; } - public HeapObjectIsOfClass (LoadedClass c) : base (c, BuildDescription (c)) { + public HeapItemIsOfClass (LoadedClass c) : base (c, BuildDescription (c)) { + } + } + + public class HeapObjectIsOfClass : HeapItemIsOfClass, IHeapObjectFilter { + public HeapObjectIsOfClass (LoadedClass c) : base (c) { + } + } + + public class AllocatedObjectIsOfClass : HeapItemIsOfClass, IAllocatedObjectFilter { + public AllocatedObjectIsOfClass (LoadedClass c) : base (c) { + } + } + + public abstract class FilterHeapObjectByClass : FilterHeapItemByClass, IHeapObjectFilter { + protected FilterHeapObjectByClass (LoadedClass c, string description) : base (c, description) { } } @@ -1072,36 +1142,45 @@ namespace Mono.Profiler { } } - public abstract class HeapObjectSet { - public static Comparison CompareHeapObjectsByID = delegate (HeapObject a, HeapObject b) { - return a.ID.CompareTo (b.ID); - }; - - public class HeapObjectSetClassStatistics { - LoadedClass c; - public LoadedClass Class { - get { - return c; - } + public class HeapItemSetClassStatistics { + LoadedClass c; + public LoadedClass Class { + get { + return c; } - uint allocatedBytes; - public uint AllocatedBytes { - get { - return allocatedBytes; - } - internal set { - allocatedBytes = value; - } + } + uint allocatedBytes; + public uint AllocatedBytes { + get { + return allocatedBytes; } - public HeapObjectSetClassStatistics (LoadedClass c, uint allocatedBytes) { - this.c = c; - this.allocatedBytes = allocatedBytes; + internal set { + allocatedBytes = value; } - - public static Comparison CompareByAllocatedBytes = delegate (HeapObjectSetClassStatistics a, HeapObjectSetClassStatistics b) { - return a.AllocatedBytes.CompareTo (b.AllocatedBytes); - }; } + public HeapItemSetClassStatistics (LoadedClass c, uint allocatedBytes) { + this.c = c; + this.allocatedBytes = allocatedBytes; + } + + public static Comparison CompareByAllocatedBytes = delegate (HeapItemSetClassStatistics a, HeapItemSetClassStatistics b) { + return a.AllocatedBytes.CompareTo (b.AllocatedBytes); + }; + } + + public interface IHeapItemSet { + bool ContainsItem (ulong id); + string ShortDescription {get;} + string LongDescription {get;} + IHeapItem[] Elements {get;} + HeapItemSetClassStatistics[] ClassStatistics {get;} + uint AllocatedBytes {get;} + } + + public abstract class HeapItemSet : IHeapItemSet where HI : IHeapItem { + public static Comparison CompareHeapItemsByID = delegate (HI a, HI b) { + return a.ID.CompareTo (b.ID); + }; string shortDescription; public string ShortDescription { @@ -1115,14 +1194,21 @@ namespace Mono.Profiler { return longDescription; } } - HeapObject[] heapObjects; - public HeapObject[] HeapObjects { + HI[] elements; + public HI[] Elements { get { - return heapObjects; + return elements; } } - HeapObjectSetClassStatistics[] classStatistics; - public HeapObjectSetClassStatistics[] ClassStatistics { + IHeapItem[] IHeapItemSet.Elements { + get { + IHeapItem[] result = new IHeapItem [elements.Length]; + Array.Copy (elements, result, elements.Length); + return result; + } + } + HeapItemSetClassStatistics[] classStatistics; + public HeapItemSetClassStatistics[] ClassStatistics { get { return classStatistics; } @@ -1134,34 +1220,73 @@ namespace Mono.Profiler { } } - protected HeapObjectSet (string shortDescription, string longDescription, HeapObject[] heapObjects) { + public void CompareWithSet (HeapItemSet otherSet, out HeapItemSet onlyInThisSet, out HeapItemSet onlyInOtherSet) where OHI : IHeapItem { + HeapItemSetFromComparison.PerformComparison (this, otherSet, out onlyInThisSet, out onlyInOtherSet); + } + + public HeapItemSet IntersectWithSet (HeapItemSet otherSet) where OHI : IHeapItem { + return HeapItemSetFromComparison.PerformIntersection (this, otherSet); + } + + public bool ContainsItem (ulong id) { + int lowIndex = -1; + int highIndex = elements.Length; + + while (true) { + int span = (highIndex - lowIndex) / 2; + + if (span > 0) { + int middleIndex = lowIndex + span; + HI middleElement = elements [middleIndex]; + ulong middleID = middleElement.ID; + if (middleID > id) { + highIndex = middleIndex; + } else if (middleID < id) { + lowIndex = middleIndex; + } else { + return true; + } + } else { + return false; + } + } + } + + public HeapItemSet ObjectsReferencingItemInSet (HeapItemSet objectSet) { + return Mono.Profiler.HeapItemSetFromComparison.ObjectsReferencingItemInSet (this, objectSet); + } + public HeapItemSet ObjectsReferencedByItemInSet (HeapItemSet objectSet) { + return Mono.Profiler.HeapItemSetFromComparison.ObjectsReferencedByItemInSet (this, objectSet); + } + + protected HeapItemSet (string shortDescription, string longDescription, HI[] elements) { this.shortDescription = shortDescription; this.longDescription = longDescription; - this.heapObjects = heapObjects; + this.elements = elements; allocatedBytes = 0; - Array.Sort (this.heapObjects, CompareHeapObjectsByID); + Array.Sort (this.elements, CompareHeapItemsByID); - Dictionary statistics = new Dictionary (); - foreach (HeapObject ho in heapObjects) { - HeapObjectSetClassStatistics cs; - if (statistics.ContainsKey (ho.Class.ID)) { - cs = statistics [ho.Class.ID]; - cs.AllocatedBytes += ho.Size; - allocatedBytes += ho.Size; + Dictionary statistics = new Dictionary (); + foreach (HI hi in elements) { + HeapItemSetClassStatistics cs; + if (statistics.ContainsKey (hi.Class.ID)) { + cs = statistics [hi.Class.ID]; + cs.AllocatedBytes += hi.Size; + allocatedBytes += hi.Size; } else { - cs = new HeapObjectSetClassStatistics (ho.Class, ho.Size); - statistics [ho.Class.ID] = cs; + cs = new HeapItemSetClassStatistics (hi.Class, hi.Size); + statistics [hi.Class.ID] = cs; } } - classStatistics = new HeapObjectSetClassStatistics [statistics.Values.Count]; + classStatistics = new HeapItemSetClassStatistics [statistics.Values.Count]; statistics.Values.CopyTo (classStatistics, 0); - Array.Sort (classStatistics, HeapObjectSetClassStatistics.CompareByAllocatedBytes); + Array.Sort (classStatistics, HeapItemSetClassStatistics.CompareByAllocatedBytes); Array.Reverse (classStatistics); } } - public class HeapObjectSetFromSnapshot : HeapObjectSet { + public class HeapObjectSetFromSnapshot : HeapItemSet { HeapSnapshot heapSnapshot; public HeapSnapshot HeapSnapshot { get { @@ -1170,77 +1295,85 @@ namespace Mono.Profiler { } public HeapObjectSetFromSnapshot (HeapSnapshot heapSnapshot): - base (String.Format ("Snapshot done at {0}", heapSnapshot.StartTime), - String.Format ("Snapshot done at {0}", heapSnapshot.StartTime), + base (String.Format ("Heap at {0}.{1:000}s", heapSnapshot.HeaderStartTime.Seconds, heapSnapshot.HeaderStartTime.Milliseconds), + String.Format ("Heap snapshot taken at {0}.{1:000}s", heapSnapshot.HeaderStartTime.Seconds, heapSnapshot.HeaderStartTime.Milliseconds), heapSnapshot.HeapObjects) { this.heapSnapshot = heapSnapshot; } } - public class HeapObjectSetFromFilter : HeapObjectSet { - HeapObjectSet baseSet; - public HeapObjectSet BaseSet { + public class AllocatedObjectSetFromEvents : HeapItemSet { + public AllocatedObjectSetFromEvents (TimeSpan timeFromStart, AllocatedObject[] allocations): + base (String.Format ("Allocations {0}.{1:000}s", timeFromStart.Seconds, timeFromStart.Milliseconds), + String.Format ("Allocations taken from {0}.{1:000}s", timeFromStart.Seconds, timeFromStart.Milliseconds), + allocations) { + } + } + + public class HeapItemSetFromFilter : HeapItemSet where HI : IHeapItem { + HeapItemSet baseSet; + public HeapItemSet BaseSet { get { return baseSet; } } - IHeapObjectFilter filter; - public IHeapObjectFilter Filter { + IHeapItemFilter filter; + public IHeapItemFilter Filter { get { return filter; } } - static HeapObject[] filterSet (HeapObjectSet baseSet, IHeapObjectFilter filter) { - List newSet = new List (); - foreach (HeapObject ho in baseSet.HeapObjects) { - if (filter.Filter (ho)) { - newSet.Add (ho); + static HI[] filterSet (HeapItemSet baseSet, IHeapItemFilter filter) { + List newSet = new List (); + foreach (HI hi in baseSet.Elements) { + if (filter.Filter (hi)) { + newSet.Add (hi); } } - HeapObject[] result = new HeapObject [newSet.Count]; + HI[] result = new HI [newSet.Count]; newSet.CopyTo (result); return result; } - public HeapObjectSetFromFilter (HeapObjectSet baseSet, IHeapObjectFilter filter): base (filter.Description, String.Format ("{0} and {1}", filter.Description, baseSet.LongDescription), filterSet (baseSet, filter)) { + public HeapItemSetFromFilter (HeapItemSet baseSet, IHeapItemFilter filter): base (filter.Description, String.Format ("{0} and {1}", filter.Description, baseSet.LongDescription), filterSet (baseSet, filter)) { this.baseSet = baseSet; this.filter = filter; } } - public class HeapObjectSetFromComparison : HeapObjectSet { - HeapObjectSet baseSet; - public HeapObjectSet BaseSet { + public class HeapItemSetFromComparison : HeapItemSet where HI : IHeapItem where OHI : IHeapItem { + HeapItemSet baseSet; + public HeapItemSet BaseSet { get { return baseSet; } } - HeapObjectSet otherSet; - public HeapObjectSet OtherSet { + HeapItemSet otherSet; + public HeapItemSet OtherSet { get { return otherSet; } } - static string buildShortDescription (HeapObjectSet otherSet) { - return String.Format("Object not in {0}", otherSet.ShortDescription); + static string buildShortDescription (HeapItemSet otherSet, string relation) { + return String.Format("Object {0} in {1}", relation, otherSet.ShortDescription); } - static string buildLongDescription (HeapObjectSet otherSet) { - return String.Format("Object not in {0}", otherSet.LongDescription); + static string buildLongDescription (HeapItemSet otherSet, string relation) { + return String.Format("Object {0} in {1}", relation, otherSet.LongDescription); } - public static void PerformComparison (HeapObjectSet firstSet, HeapObjectSet secondSet, out HeapObjectSet onlyInFirstSet, out HeapObjectSet onlyInSecondSet) { - List onlyInFirst = new List (); - List onlyInSecond = new List (); + public static void PerformComparison (HeapItemSet firstSet, HeapItemSet secondSet, out HeapItemSet onlyInFirstSet, out HeapItemSet onlyInSecondSet) where HI1 : IHeapItem where HI2 : IHeapItem { + List onlyInFirst = new List (); + List onlyInSecond = new List (); int firstIndex = 0; int secondIndex = 0; - HeapObject[] firstObjects = firstSet.HeapObjects; - HeapObject[] secondObjects = secondSet.HeapObjects; + HI1[] firstObjects = firstSet.Elements; + HI2[] secondObjects = secondSet.Elements; while ((firstIndex < firstObjects.Length) || (secondIndex < secondObjects.Length)) { if (firstIndex >= firstObjects.Length) { @@ -1254,8 +1387,8 @@ namespace Mono.Profiler { firstIndex ++; } } else { - HeapObject firstObject = firstObjects [firstIndex]; - HeapObject secondObject = secondObjects [secondIndex]; + HI1 firstObject = firstObjects [firstIndex]; + HI2 secondObject = secondObjects [secondIndex]; if (firstObject.ID < secondObject.ID) { onlyInFirst.Add (firstObject); firstIndex ++; @@ -1269,11 +1402,80 @@ namespace Mono.Profiler { } } - onlyInFirstSet = new HeapObjectSetFromComparison(firstSet, secondSet, onlyInFirst.ToArray ()); - onlyInSecondSet = new HeapObjectSetFromComparison(secondSet, firstSet, onlyInSecond.ToArray ()); + onlyInFirstSet = new HeapItemSetFromComparison(firstSet, secondSet, onlyInFirst.ToArray (), "not"); + onlyInSecondSet = new HeapItemSetFromComparison(secondSet, firstSet, onlyInSecond.ToArray (), "not"); + } + + public static HeapItemSet PerformIntersection (HeapItemSet firstSet, HeapItemSet secondSet) where HI1 : IHeapItem where HI2 : IHeapItem { + List result = new List (); + + int firstIndex = 0; + int secondIndex = 0; + HI1[] firstObjects = firstSet.Elements; + HI2[] secondObjects = secondSet.Elements; + + Console.WriteLine ("Inside PerformIntersection..."); + + while ((firstIndex < firstObjects.Length) && (secondIndex < secondObjects.Length)) { + HI1 firstObject = firstObjects [firstIndex]; + HI2 secondObject = secondObjects [secondIndex]; + if (firstObject.ID < secondObject.ID) { + firstIndex ++; + } else if (secondObject.ID < firstObject.ID) { + secondIndex ++; + } else { + result.Add (firstObject); + firstIndex ++; + secondIndex ++; + } + } + + return new HeapItemSetFromComparison(firstSet, secondSet, result.ToArray (), "also"); + } + + static bool ObjectReferencesItemInSet (HeapItemSet itemSet, HeapObject o) { + foreach (HeapObject reference in o.References) { + if (itemSet.ContainsItem (reference.ID)) { + return true; + } + } + return false; + } + public static HeapItemSet ObjectsReferencingItemInSet (HeapItemSet itemSet, HeapItemSet objectSet) { + List result = new List (); + HeapObject[] objects = objectSet.Elements; + + foreach (HeapObject o in objects) { + if (ObjectReferencesItemInSet (itemSet, o)) { + result.Add (o); + } + } + + return new HeapItemSetFromComparison(objectSet, itemSet, result.ToArray (), "references item"); + } + + static bool ObjectIsReferencedByItemInSet (HeapItemSet itemSet, HeapObject o) { + foreach (HeapObject reference in o.BackReferences) { + if (itemSet.ContainsItem (reference.ID)) { + return true; + } + } + return false; + } + public static HeapItemSet ObjectsReferencedByItemInSet (HeapItemSet itemSet, HeapItemSet objectSet) { + List result = new List (); + HeapObject[] objects = objectSet.Elements; + + foreach (HeapObject o in objects) { + if (ObjectIsReferencedByItemInSet (itemSet, o)) { + result.Add (o); + } + } + + return new HeapItemSetFromComparison(objectSet, itemSet, result.ToArray (), "references item"); } - HeapObjectSetFromComparison (HeapObjectSet baseSet, HeapObjectSet otherSet, HeapObject[] heapObjects): base (buildShortDescription (otherSet), buildLongDescription (otherSet), heapObjects) { + HeapItemSetFromComparison (HeapItemSet baseSet, HeapItemSet otherSet, HI[] heapItems, string relation): base (buildShortDescription (otherSet, relation), buildLongDescription (otherSet, relation), heapItems) { this.baseSet = baseSet; this.otherSet = otherSet; } @@ -1299,8 +1501,8 @@ namespace Mono.Profiler { public ExecutableMemoryRegion NewExecutableMemoryRegion (uint id, string fileName, uint fileOffset, ulong startAddress, ulong endAddress) { return new ExecutableMemoryRegion (id, fileName, fileOffset, startAddress, endAddress); } - public HeapSnapshot NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, LoadedClass[] initialAllocations, bool recordSnapshots) { - return new HeapSnapshot (collection, startCounter, startTime, endCounter, endTime, initialAllocations, recordSnapshots); + public HeapSnapshot NewHeapSnapshot (uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, TimeSpan headerStartTime, LoadedClass[] initialAllocations, bool recordSnapshots) { + return new HeapSnapshot (collection, startCounter, startTime, endCounter, endTime, headerStartTime, initialAllocations, recordSnapshots); } public UnmanagedFunctionFromID NewUnmanagedFunction (uint id, string name, ExecutableMemoryRegion region) { return new UnmanagedFunctionFromID (id, name, region); diff --git a/Mono.Profiler/profiler-decoder-library/Reader.cs b/Mono.Profiler/profiler-decoder-library/Reader.cs index 59b69ea2..b0b2f3ef 100644 --- a/Mono.Profiler/profiler-decoder-library/Reader.cs +++ b/Mono.Profiler/profiler-decoder-library/Reader.cs @@ -48,6 +48,7 @@ namespace Mono.Profiler { return hasEnded; } } + ulong counter = 0; byte[] cachedData; public virtual void RecycleData (byte [] data) { @@ -91,10 +92,11 @@ namespace Mono.Profiler { if (code == BlockCode.END) { hasEnded = true; } + counter += BlockData.DecodeHeaderBlockCounterDelta (header); block = NewData (length); stream.Read (block, 0, length); - result = new BlockData (fileOffset, code, length, block); + result = new BlockData (fileOffset, code, length, counter, block); fileOffset += (uint) length; return result; @@ -247,7 +249,7 @@ namespace Mono.Profiler { blocks = result.ToArray (); foreach (Block block in blocks) { - block.TimeFromStart = eventProcessor.clicksToTimeSpan (block.Counter); + block.TimeFromStart = eventProcessor.ClicksToTimeSpan (block.Counter); } } @@ -255,7 +257,7 @@ namespace Mono.Profiler { stream.Seek (block.FileOffset, SeekOrigin.Begin); byte[] data = NewData ((int) block.Length); stream.Read (data, 0, (int) block.Length); - return new BlockData (block.FileOffset, block.Code, (int) block.Length, data); + return new BlockData (block.FileOffset, block.Code, (int) block.Length, block.Counter, data); } public SeekableLogFileReader (System.IO.FileStream stream) { diff --git a/Mono.Profiler/profiler-file-decoder/ChangeLog b/Mono.Profiler/profiler-file-decoder/ChangeLog index 9153e585..74662141 100644 --- a/Mono.Profiler/profiler-file-decoder/ChangeLog +++ b/Mono.Profiler/profiler-file-decoder/ChangeLog @@ -1,3 +1,6 @@ +2008-11-03 Massimiliano Mantione + * Main.cs: Changed clicksToSeconds to ClicksToSeconds after refactoring. + 2008-10-10 Massimiliano Mantione * Main.cs: - Added support for handling the stack trace of each allocation event. diff --git a/Mono.Profiler/profiler-file-decoder/Main.cs b/Mono.Profiler/profiler-file-decoder/Main.cs index fd28700e..e620b9c6 100644 --- a/Mono.Profiler/profiler-file-decoder/Main.cs +++ b/Mono.Profiler/profiler-file-decoder/Main.cs @@ -149,7 +149,7 @@ namespace Mono.Profiler writer.WriteLine ("Reporting execution time (on {0} methods)", methods.Length); foreach (LoadedMethod m in methods) { if (m.Clicks > 0) { - writer.WriteLine ("{0,5:F2}% ({1:F6}s) {2}.{3}", ((((double)m.Clicks) / totalExecutionClicks) * 100), data.clicksToSeconds (m.Clicks), m.Class.Name, m.Name); + writer.WriteLine ("{0,5:F2}% ({1:F6}s) {2}.{3}", ((((double)m.Clicks) / totalExecutionClicks) * 100), data.ClicksToSeconds (m.Clicks), m.Class.Name, m.Name); LoadedMethod.CallsPerCallerMethod[] callsPerCallerMethodArray = m.Callers; if (callsPerCallerMethodArray.Length > 0) { Array.Sort (callsPerCallerMethodArray, LoadedMethod.CallsPerCallerMethod.CompareByCalls); @@ -176,7 +176,7 @@ namespace Mono.Profiler writer.WriteLine ("Reporting jit time (on {0} methods)", methods.Length); foreach (LoadedMethod m in methods) { if (m.JitClicks > 0) { - writer.WriteLine ("{0,5:F2}% ({1:F3}ms) {2}.{3}", ((((double)m.JitClicks) / totalJitClicks) * 100), data.clicksToSeconds (m.JitClicks) * 1000, m.Class.Name, m.Name); + writer.WriteLine ("{0,5:F2}% ({1:F3}ms) {2}.{3}", ((((double)m.JitClicks) / totalJitClicks) * 100), data.ClicksToSeconds (m.JitClicks) * 1000, m.Class.Name, m.Name); } } } else { @@ -220,7 +220,7 @@ namespace Mono.Profiler ProfilerEventHandler.GcStatistics[] gcStatistics = data.GarbageCollectioncStatistics; if (gcStatistics.Length > 0) { - double totalTime = data.clicksToSeconds (data.EndCounter - data.StartCounter); + double totalTime = data.ClicksToSeconds (data.EndCounter - data.StartCounter); double gcTime = 0; double gcMarkTime = 0; double gcSweepTime = 0; @@ -246,7 +246,7 @@ namespace Mono.Profiler ulong gcStartClicks = gcs.StartCounter - data.StartCounter; writer.WriteLine ("[{0}] Collection starting at {1:F3}s (generation {2}): duration {3:F3}ms, mark {4:F3}ms, sweep {5:F3}ms", gcs.Collection, - data.clicksToSeconds (gcStartClicks), + data.ClicksToSeconds (gcStartClicks), gcs.Generation, gcs.Duration * 1000, gcs.MarkDuration * 1000, @@ -284,8 +284,8 @@ namespace Mono.Profiler HeapSnapshot.AllocationStatisticsPerClass [] allocationStatistics = heapSnapshot.AllocationStatistics; writer.WriteLine ("Heap data collection {0} started at {1} (duration {2:F3}ms)", heapSnapshot.Collection, - data.counterToDateTime (heapSnapshot.StartCounter), - data.clicksToSeconds (heapSnapshot.EndCounter - heapSnapshot.StartCounter) * 1000); + data.CounterToDateTime (heapSnapshot.StartCounter), + data.ClicksToSeconds (heapSnapshot.EndCounter - heapSnapshot.StartCounter) * 1000); if (allocationStatistics.Length > 0) { Array.Sort (allocationStatistics, HeapSnapshot.AllocationStatisticsPerClass.CompareByAllocatedBytes); Array.Reverse (allocationStatistics); -- cgit v1.2.3