Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/ChangeLog9
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/HeapExplorerActions.cs2
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs302
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/HeapSnapshotExplorer.cs415
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/LoadedClassChooser.cs6
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/gtk-gui/gui.stetic2
-rw-r--r--Mono.Profiler/heap-snapshot-viewer/ChangeLog4
-rw-r--r--Mono.Profiler/heap-snapshot-viewer/Main.cs6
-rw-r--r--Mono.Profiler/profiler-decoder-library/BaseTypes.cs30
-rw-r--r--Mono.Profiler/profiler-decoder-library/ChangeLog17
-rw-r--r--Mono.Profiler/profiler-decoder-library/Decoder.cs13
-rw-r--r--Mono.Profiler/profiler-decoder-library/EventProcessor.cs66
-rw-r--r--Mono.Profiler/profiler-decoder-library/ObjectModel.cs390
-rw-r--r--Mono.Profiler/profiler-decoder-library/Reader.cs8
-rw-r--r--Mono.Profiler/profiler-file-decoder/ChangeLog3
-rw-r--r--Mono.Profiler/profiler-file-decoder/Main.cs12
16 files changed, 1010 insertions, 275 deletions
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 <massi@ximian.com>
+ * 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 <massi@ximian.com>
* 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<HI> : INode where HI : IHeapItem {
+ public abstract HeapItemSet<HI> Items {get;}
+ IHeapItemSet INode.Items {
+ get {
+ return Items;
+ }
}
- public abstract string Description {
- get;
+
+ protected abstract SubSetNode<HI> NewSubSet (HeapItemSet<HI> 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<HI> parent;
+ public Node<HI> Parent {
+ get {
+ return parent;
+ }
+ }
+ INode INode.Parent {
get {
return parent;
}
}
- public Node Root {
+ public Node<HI> 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<HI> Filter (IHeapItemFilter<HI> filter) {
+ HeapItemSetFromFilter<HI> subSet = new HeapItemSetFromFilter<HI> (Items, filter);
+ SubSetNode<HI> 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<OHI> (Node<OHI> otherNode) where OHI : IHeapItem {
+ HeapItemSet<HI> onlyInThisSet;
+ HeapItemSet<OHI> onlyInOtherSet;
+ Items.CompareWithSet (otherNode.Items, out onlyInThisSet, out onlyInOtherSet);
+ NewSubSet (onlyInThisSet);
+ otherNode.NewSubSet (onlyInOtherSet);
+ }
+
+ public void IntersectWithNode<OHI> (Node<OHI> otherNode) where OHI : IHeapItem {
+ NewSubSet (Items.IntersectWithSet (otherNode.Items));
}
- protected Node (HeapExplorerTreeModel model, Node parent) {
+ public void SelectObjectsReferencingItem (Node<HeapObject> objectsNode) {
+ objectsNode.NewSubSet (Items.ObjectsReferencingItemInSet (objectsNode.Items));
+ }
+
+ public void SelectObjectsReferencedByItem (Node<HeapObject> objectsNode) {
+ objectsNode.NewSubSet (Items.ObjectsReferencedByItemInSet (objectsNode.Items));
+ }
+
+ public abstract Menu ContextMenu {get;}
+
+ protected Node (HeapExplorerTreeModel model, Node<HI> parent) {
this.model = model;
this.parent = parent;
this.treeIter = HandleNodeCreation ();
}
}
- public class SnapshotNode : Node {
+ public class SnapshotNode : Node<HeapObject>, IRootNode {
SeekableLogFileReader.Block heapBlock;
HeapSnapshot snapshot;
@@ -125,49 +170,185 @@ namespace Mono.Profiler
}
}
- HeapObjectSetFromSnapshot objects;
- public override HeapObjectSet Objects {
+ HeapObjectSetFromSnapshot items;
+ public override HeapItemSet<HeapObject> 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<HeapObject> NewSubSet (HeapItemSet<HeapObject> 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<AllocatedObject>, IRootNode {
+ SeekableLogFileReader.Block[] eventBlocks;
+
+ AllocatedObjectSetFromEvents items;
+ public override HeapItemSet<AllocatedObject> 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<AllocatedObject> NewSubSet (HeapItemSet<AllocatedObject> 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<HI> : Node<HI> where HI : IHeapItem {
+ HeapItemSet<HI> items;
+ public override HeapItemSet<HI> Items {
+ get {
+ return items;
+ }
+ }
+
+ protected SubSetNode (HeapExplorerTreeModel model, Node<HI> parent, HeapItemSet<HI> items) : base (model, parent) {
+ this.items = items;
+ }
+ }
+
+ public class HeapObjectSubSetNode : SubSetNode<HeapObject> {
+ protected override SubSetNode<HeapObject> NewSubSet (HeapItemSet<HeapObject> 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<HeapObject> parent, HeapItemSet<HeapObject> items) : base (model, parent, items) {
+ }
+ }
+
+ public class AllocatedObjectSubSetNode : SubSetNode<AllocatedObject> {
+ protected override SubSetNode<AllocatedObject> NewSubSet (HeapItemSet<AllocatedObject> 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<AllocatedObject> parent, HeapItemSet<AllocatedObject> items) : base (model, parent, items) {
}
}
@@ -207,35 +388,66 @@ namespace Mono.Profiler
}
protected HeapEventProcessor heapEventProcessor;
- List<SnapshotNode> rootNodes;
- public SnapshotNode[] RootNodes {
+ List<IRootNode> rootNodes;
+ public IRootNode[] RootNodes {
get {
return rootNodes.ToArray ();
}
}
+ HeapSnapshotExplorer explorer;
+ public HeapSnapshotExplorer Explorer {
+ get {
+ return explorer;
+ }
+ }
+
+ AllocationsNode CreateAllocationsNode (List<SeekableLogFileReader.Block> 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<SeekableLogFileReader.Block> eventBlocks = new List<SeekableLogFileReader.Block> ();
+ 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<SnapshotNode> ();
+ this.explorer = explorer;
+ rootNodes = new List<IRootNode> ();
}
}
}
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<HeapObject> markedObjectNode;
+ public HeapExplorerTreeModel.Node<HeapObject> MarkedObjectNode {
+ get {
+ return markedObjectNode;
+ }
+ }
+ HeapExplorerTreeModel.Node<AllocatedObject> markedAllocationNode;
+ public HeapExplorerTreeModel.Node<AllocatedObject> 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<HeapObject> ();
};
- 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<AllocatedObject> ();
+ };
+ 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<HeapObject> ();
+ };
+ compareObjectSet.Append (menuItem);
+ menuItem = new MenuItem ("Perform intersection with this set");
+ menuItem.Activated += delegate {
+ OnIntersectWithSet<HeapObject> ();
+ };
+ 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<AllocatedObject> ();
};
- 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<AllocatedObject> ();
};
- 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<HeapObject> ();
+ };
+ filterObjectSetUsingSelection.Append (menuItem);
+ menuItem = new MenuItem ("Select objects referenced by objects in this set");
+ menuItem.Activated += delegate {
+ OnFilterByIsReferencedByObjectInSet<HeapObject> ();
+ };
+ 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<AllocatedObject> ();
+ };
+ filterAllocationSetUsingSelection.Append (menuItem);
+ menuItem = new MenuItem ("Select objects referenced by objects in this set");
+ menuItem.Activated += delegate {
+ OnFilterByIsReferencedByObjectInSet<AllocatedObject> ();
+ };
+ 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<HI> () where HI : IHeapItem {
+ HeapExplorerTreeModel.Node<HI> node = CurrentSelection as HeapExplorerTreeModel.Node<HI>;
+ if (node != null) {
+ LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Items.ClassStatistics);
if (c != null) {
- IHeapObjectFilter filter = new HeapObjectIsOfClass (c);
- CurrentSelection.Filter (filter);
+ HeapItemIsOfClass<HI> filter = new HeapItemIsOfClass<HI> (c);
+ node.Filter (filter);
}
}
}
public void OnFilterByReferencesObjectOfClass () {
- if (CurrentSelection != null) {
- LoadedClass c = LoadedClassChooser.ChooseClass (CurrentSelection.Root.Objects.ClassStatistics);
+ HeapExplorerTreeModel.Node<HeapObject> node = CurrentSelection as HeapExplorerTreeModel.Node<HeapObject>;
+ 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<HeapObject> node = CurrentSelection as HeapExplorerTreeModel.Node<HeapObject>;
+ 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<HeapObject>;
+ markedAllocationNode = null;
+ markIsForComparison = true;
+ markIsForFiltering = false;
+ }
+
+ public void OnMarkObjectSetForFiltering () {
+ markedObjectNode = CurrentSelection as HeapExplorerTreeModel.Node<HeapObject>;
+ markedAllocationNode = null;
+ markIsForComparison = false;
+ markIsForFiltering = true;
}
- public void OnClearSetForComparison () {
- NodeSelectedForComparison = null;
+ public void OnMarkAllocationSetForComparison () {
+ markedObjectNode = null;
+ markedAllocationNode = CurrentSelection as HeapExplorerTreeModel.Node<AllocatedObject>;
+ 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<AllocatedObject>;
+ markIsForComparison = false;
+ markIsForFiltering = true;
+ }
+
+ public void OnClearMark () {
+ markedObjectNode = null;
+ markedAllocationNode = null;
+ markIsForComparison = false;
+ markIsForFiltering = false;
+ }
+
+ public void OnCompareWithSet<HI> () where HI : IHeapItem {
+ HeapExplorerTreeModel.Node<HI> node = CurrentSelection as HeapExplorerTreeModel.Node<HI>;
+ if (node != null) {
+ if (markedObjectNode != null) {
+ node.CompareWithNode (markedObjectNode);
+ } else if (markedAllocationNode != null) {
+ node.CompareWithNode (markedAllocationNode);
+ }
+ OnClearMark ();
}
}
+ public void OnIntersectWithSet<HI> () where HI : IHeapItem {
+ HeapExplorerTreeModel.Node<HI> node = CurrentSelection as HeapExplorerTreeModel.Node<HI>;
+ if (node != null) {
+ if (markedObjectNode != null) {
+ markedObjectNode.IntersectWithNode (node);
+ } else if (markedAllocationNode != null) {
+ markedAllocationNode.IntersectWithNode (node);
+ }
+ OnClearMark ();
+ }
+ }
+
+ public void OnFilterByReferencesObjectInSet<HI> () where HI : IHeapItem {
+ HeapExplorerTreeModel.Node<HI> itemNode = CurrentSelection as HeapExplorerTreeModel.Node<HI>;
+ if ((itemNode != null) && (markedObjectNode != null)) {
+ itemNode.SelectObjectsReferencingItem (markedObjectNode);
+ OnClearMark ();
+ }
+ }
+ public void OnFilterByIsReferencedByObjectInSet<HI> () where HI : IHeapItem {
+ HeapExplorerTreeModel.Node<HI> itemNode = CurrentSelection as HeapExplorerTreeModel.Node<HI>;
+ 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 @@
<target-gtk-version>2.12.1</target-gtk-version>
</configuration>
<import>
- <widget-library name="../bin/Debug/heap-snapshot-explorer.dll" internal="true" />
+ <widget-library name="../bin/Debug/mprof-heap-snapshot-explorer.dll" internal="true" />
</import>
<action-group name="Mono.Profiler.HeapExplorerActions">
<action id="loadDataAction">
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 <massi@ximian.com>
+ * Main.cs: Added "explorer" parameter to the model constructor, and
+ removed debugging code.
+
2008-08-20 Massimiliano Mantione <massi@ximian.com>
* 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<HO,LC> heapObjectFactory, uint collection, ulong startCounter, DateTime startTime, ulong endCounter, DateTime endTime, bool recordSnapshot) {
+ public BaseHeapSnapshot (HeapObjectFactory<HO,LC> 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<ulong,HO> ();
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<HS> 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 <massi@ximian.com>
+ * 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 <massi@ximian.com>
* 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<AllocatedObject> allocatedObjects = null;
+ public bool RecordAllocations {
+ get {
+ return allocatedObjects != null;
+ }
+ set {
+ if (value) {
+ if (allocatedObjects != null) {
+ allocatedObjects.Clear ();
+ } else {
+ allocatedObjects = new List<AllocatedObject> ();
+ }
+ } 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<HeapObject,LoadedClass> {
+ public interface IHeapItem : IAllocatedObject<LoadedClass> {
+ }
+
+ public class HeapObject : BaseHeapObject<HeapObject,LoadedClass>, 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<HeapObject,LoadedClass> {
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<HI> where HI : IHeapItem {
string Description {
get;
}
- bool Filter (HeapObject heapObject);
+ bool Filter (HI heapItem);
+ }
+ public interface IAllocatedObjectFilter : IHeapItemFilter<AllocatedObject> {
+ }
+ public interface IHeapObjectFilter : IHeapItemFilter<HeapObject> {
}
- public abstract class FilterHeapObjectByClass : IHeapObjectFilter {
+ public abstract class FilterHeapItemByClass<HI> : IHeapItemFilter<HI> 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<HI> : FilterHeapItemByClass<HI> 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<HeapObject>, IHeapObjectFilter {
+ public HeapObjectIsOfClass (LoadedClass c) : base (c) {
+ }
+ }
+
+ public class AllocatedObjectIsOfClass : HeapItemIsOfClass<AllocatedObject>, IAllocatedObjectFilter {
+ public AllocatedObjectIsOfClass (LoadedClass c) : base (c) {
+ }
+ }
+
+ public abstract class FilterHeapObjectByClass : FilterHeapItemByClass<HeapObject>, IHeapObjectFilter {
+ protected FilterHeapObjectByClass (LoadedClass c, string description) : base (c, description) {
}
}
@@ -1072,36 +1142,45 @@ namespace Mono.Profiler {
}
}
- public abstract class HeapObjectSet {
- public static Comparison<HeapObject> 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<HeapObjectSetClassStatistics> 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<HeapItemSetClassStatistics> 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<HI> : IHeapItemSet where HI : IHeapItem {
+ public static Comparison<HI> 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<OHI> (HeapItemSet<OHI> otherSet, out HeapItemSet<HI> onlyInThisSet, out HeapItemSet<OHI> onlyInOtherSet) where OHI : IHeapItem {
+ HeapItemSetFromComparison<HI,OHI>.PerformComparison<HI,OHI> (this, otherSet, out onlyInThisSet, out onlyInOtherSet);
+ }
+
+ public HeapItemSet<HI> IntersectWithSet<OHI> (HeapItemSet<OHI> otherSet) where OHI : IHeapItem {
+ return HeapItemSetFromComparison<HI,OHI>.PerformIntersection<HI,OHI> (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<HeapObject> ObjectsReferencingItemInSet (HeapItemSet<HeapObject> objectSet) {
+ return Mono.Profiler.HeapItemSetFromComparison<HI,HeapObject>.ObjectsReferencingItemInSet (this, objectSet);
+ }
+ public HeapItemSet<HeapObject> ObjectsReferencedByItemInSet (HeapItemSet<HeapObject> objectSet) {
+ return Mono.Profiler.HeapItemSetFromComparison<HI,HeapObject>.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<ulong,HeapObjectSetClassStatistics> statistics = new Dictionary<ulong,HeapObjectSetClassStatistics> ();
- 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<ulong,HeapItemSetClassStatistics> statistics = new Dictionary<ulong,HeapItemSetClassStatistics> ();
+ 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<HeapObject> {
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<AllocatedObject> {
+ 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<HI> : HeapItemSet<HI> where HI : IHeapItem {
+ HeapItemSet<HI> baseSet;
+ public HeapItemSet<HI> BaseSet {
get {
return baseSet;
}
}
- IHeapObjectFilter filter;
- public IHeapObjectFilter Filter {
+ IHeapItemFilter<HI> filter;
+ public IHeapItemFilter<HI> Filter {
get {
return filter;
}
}
- static HeapObject[] filterSet (HeapObjectSet baseSet, IHeapObjectFilter filter) {
- List<HeapObject> newSet = new List<HeapObject> ();
- foreach (HeapObject ho in baseSet.HeapObjects) {
- if (filter.Filter (ho)) {
- newSet.Add (ho);
+ static HI[] filterSet (HeapItemSet<HI> baseSet, IHeapItemFilter<HI> filter) {
+ List<HI> newSet = new List<HI> ();
+ 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<HI> baseSet, IHeapItemFilter<HI> 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<HI,OHI> : HeapItemSet<HI> where HI : IHeapItem where OHI : IHeapItem {
+ HeapItemSet<HI> baseSet;
+ public HeapItemSet<HI> BaseSet {
get {
return baseSet;
}
}
- HeapObjectSet otherSet;
- public HeapObjectSet OtherSet {
+ HeapItemSet<OHI> otherSet;
+ public HeapItemSet<OHI> OtherSet {
get {
return otherSet;
}
}
- static string buildShortDescription (HeapObjectSet otherSet) {
- return String.Format("Object not in {0}", otherSet.ShortDescription);
+ static string buildShortDescription (HeapItemSet<OHI> 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<OHI> 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<HeapObject> onlyInFirst = new List<HeapObject> ();
- List<HeapObject> onlyInSecond = new List<HeapObject> ();
+ public static void PerformComparison<HI1,HI2> (HeapItemSet<HI1> firstSet, HeapItemSet<HI2> secondSet, out HeapItemSet<HI1> onlyInFirstSet, out HeapItemSet<HI2> onlyInSecondSet) where HI1 : IHeapItem where HI2 : IHeapItem {
+ List<HI1> onlyInFirst = new List<HI1> ();
+ List<HI2> onlyInSecond = new List<HI2> ();
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<HI1,HI2>(firstSet, secondSet, onlyInFirst.ToArray (), "not");
+ onlyInSecondSet = new HeapItemSetFromComparison<HI2,HI1>(secondSet, firstSet, onlyInSecond.ToArray (), "not");
+ }
+
+ public static HeapItemSet<HI1> PerformIntersection<HI1,HI2> (HeapItemSet<HI1> firstSet, HeapItemSet<HI2> secondSet) where HI1 : IHeapItem where HI2 : IHeapItem {
+ List<HI1> result = new List<HI1> ();
+
+ 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<HI1,HI2>(firstSet, secondSet, result.ToArray (), "also");
+ }
+
+ static bool ObjectReferencesItemInSet (HeapItemSet<HI> itemSet, HeapObject o) {
+ foreach (HeapObject reference in o.References) {
+ if (itemSet.ContainsItem (reference.ID)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public static HeapItemSet<HeapObject> ObjectsReferencingItemInSet (HeapItemSet<HI> itemSet, HeapItemSet<HeapObject> objectSet) {
+ List<HeapObject> result = new List<HeapObject> ();
+ HeapObject[] objects = objectSet.Elements;
+
+ foreach (HeapObject o in objects) {
+ if (ObjectReferencesItemInSet (itemSet, o)) {
+ result.Add (o);
+ }
+ }
+
+ return new HeapItemSetFromComparison<HeapObject,HI>(objectSet, itemSet, result.ToArray (), "references item");
+ }
+
+ static bool ObjectIsReferencedByItemInSet (HeapItemSet<HI> itemSet, HeapObject o) {
+ foreach (HeapObject reference in o.BackReferences) {
+ if (itemSet.ContainsItem (reference.ID)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public static HeapItemSet<HeapObject> ObjectsReferencedByItemInSet (HeapItemSet<HI> itemSet, HeapItemSet<HeapObject> objectSet) {
+ List<HeapObject> result = new List<HeapObject> ();
+ HeapObject[] objects = objectSet.Elements;
+
+ foreach (HeapObject o in objects) {
+ if (ObjectIsReferencedByItemInSet (itemSet, o)) {
+ result.Add (o);
+ }
+ }
+
+ return new HeapItemSetFromComparison<HeapObject,HI>(objectSet, itemSet, result.ToArray (), "references item");
}
- HeapObjectSetFromComparison (HeapObjectSet baseSet, HeapObjectSet otherSet, HeapObject[] heapObjects): base (buildShortDescription (otherSet), buildLongDescription (otherSet), heapObjects) {
+ HeapItemSetFromComparison (HeapItemSet<HI> baseSet, HeapItemSet<OHI> 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 <massi@ximian.com>
+ * Main.cs: Changed clicksToSeconds to ClicksToSeconds after refactoring.
+
2008-10-10 Massimiliano Mantione <massi@ximian.com>
* 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);