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:
Diffstat (limited to 'Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs')
-rw-r--r--Mono.Profiler/heap-snapshot-explorer/HeapExplorerTreeModel.cs302
1 files changed, 257 insertions, 45 deletions
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> ();
}
}
}