diff options
author | Massimiliano Mantione <massi@mono-cvs.ximian.com> | 2009-06-24 18:18:09 +0400 |
---|---|---|
committer | Massimiliano Mantione <massi@mono-cvs.ximian.com> | 2009-06-24 18:18:09 +0400 |
commit | a2b3b9690434e1da622bc8f907d774b56a668735 (patch) | |
tree | 69d51eb1db13bcc00813831c79edae2d48132e6f /Mono.Profiler | |
parent | 21a8dc7e6d773a99cab5265cd146d49a07902246 (diff) |
Build direct and reverse call trees for statistical events.
svn path=/trunk/mono-tools/; revision=136769
Diffstat (limited to 'Mono.Profiler')
-rw-r--r-- | Mono.Profiler/profiler-decoder-library/ChangeLog | 4 | ||||
-rw-r--r-- | Mono.Profiler/profiler-decoder-library/EventProcessor.cs | 73 | ||||
-rw-r--r-- | Mono.Profiler/profiler-decoder-library/ObjectModel.cs | 89 |
3 files changed, 154 insertions, 12 deletions
diff --git a/Mono.Profiler/profiler-decoder-library/ChangeLog b/Mono.Profiler/profiler-decoder-library/ChangeLog index d39ad7d0..ebd36c33 100644 --- a/Mono.Profiler/profiler-decoder-library/ChangeLog +++ b/Mono.Profiler/profiler-decoder-library/ChangeLog @@ -1,3 +1,7 @@ +2009-06-24 Massimiliano Mantione <massi@ximian.com> + * ObjectModel.cs, EventProcessor.cs: + Build direct and reverse call trees for statistical events. + 2009-06-18 Massimiliano Mantione <massi@ximian.com> * BaseTypes.cs, Decoder.cs, ObjectModel.cs, EventProcessor.cs: Added assembly information to classes and wrapper flag to methods. diff --git a/Mono.Profiler/profiler-decoder-library/EventProcessor.cs b/Mono.Profiler/profiler-decoder-library/EventProcessor.cs index b987941b..b0f4ced8 100644 --- a/Mono.Profiler/profiler-decoder-library/EventProcessor.cs +++ b/Mono.Profiler/profiler-decoder-library/EventProcessor.cs @@ -317,30 +317,66 @@ namespace Mono.Profiler { uint remainingCallersInChain; IStatisticalHitItem lastCallee; + StatisticalHitItemTreeNode lastCalleeNode; + bool eventsArePartOfChain; + int currentChainIndex; + IStatisticalHitItem[] currentChain; // Returns true if the hit must be counted (this is the first chain item) bool HandleCallChain (IStatisticalHitItem caller) { - bool result; - - if (remainingCallersInChain > 0) { - remainingCallersInChain --; + if (eventsArePartOfChain) { + bool result; + if (lastCallee != null) { - //Console.WriteLine ("HandleCallChain[{0}] {1} on {2}", remainingCallersInChain, caller.Name, lastCallee.Name); lastCallee.CallCounts.AddCaller (caller); caller.CallCounts.AddCallee (lastCallee); } - result = false; + + if (lastCalleeNode != null) { + lastCalleeNode = lastCalleeNode.AddChild (caller); + } else { + lastCalleeNode = statisticalItemsByCaller.AddChild (caller); + } + + currentChain [currentChainIndex] = caller; + currentChainIndex ++; + + if (remainingCallersInChain > 0) { + //Console.WriteLine ("HandleCallChain[{0}] {1} on {2}", remainingCallersInChain, caller.Name, lastCallee.Name); + remainingCallersInChain --; + result = false; + } else { + //Console.WriteLine ("HandleCallChain[{0}] {1}", remainingCallersInChain, caller.Name); + result = true; + + StatisticalHitItemTreeNode currentNode = statisticalItemsByCallee; + while (currentChainIndex > 0) { + currentChainIndex --; + currentNode = currentNode.AddChild (currentChain [currentChainIndex]); + } + + eventsArePartOfChain = false; + Array.Clear (currentChain, 0, currentChain.Length); + } + + lastCallee = caller; + + return result; } else { - //Console.WriteLine ("HandleCallChain[{0}] {1}", remainingCallersInChain, caller.Name); - result = true; + return true; } - - lastCallee = caller; - - return result; } public override void StatisticalCallChainStart (uint chainDepth) { + lastCallee = null; + lastCalleeNode = null; remainingCallersInChain = chainDepth; + eventsArePartOfChain = true; + currentChainIndex = 0; + if (currentChain != null) { + Array.Clear (currentChain, 0, currentChain.Length); + } else { + currentChain = new IStatisticalHitItem [32]; + } //Console.WriteLine ("StatisticalCallChainStart ({0})", chainDepth); } @@ -406,6 +442,19 @@ namespace Mono.Profiler { } } + StatisticalHitItemTreeNode statisticalItemsByCaller = new StatisticalHitItemTreeNode (null); + public StatisticalHitItemTreeNode[] StatisticalItemsByCaller { + get { + return statisticalItemsByCaller.Children; + } + } + StatisticalHitItemTreeNode statisticalItemsByCallee = new StatisticalHitItemTreeNode (null); + public StatisticalHitItemTreeNode[] StatisticalItemsByCallee { + get { + return statisticalItemsByCallee.Children; + } + } + public class GcStatistics { ProfilerEventHandler data; diff --git a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs index 41e7ae33..0579766d 100644 --- a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs +++ b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs @@ -729,6 +729,95 @@ namespace Mono.Profiler { StatisticalHitItemCallCounts CallCounts {get;} } + public class StatisticalHitItemTreeNode { + IStatisticalHitItem item; + public IStatisticalHitItem Item { + get { + return item; + } + } + + public string Name { + get { + return item.Name; + } + } + + uint hitCount; + void IncrementHitCount () { + hitCount ++; + } + public uint HitCount { + get { + return hitCount; + } + } + + public static Comparison<StatisticalHitItemTreeNode> CompareByHitCount = delegate (StatisticalHitItemTreeNode a, StatisticalHitItemTreeNode b) { + int result = b.HitCount.CompareTo (a.HitCount); + if (result == 0) { + result = a.Name.CompareTo (b.Name); + } + return result; + }; + + + Dictionary<string,StatisticalHitItemTreeNode> children; + static StatisticalHitItemTreeNode[] emptyChildren = new StatisticalHitItemTreeNode [0]; + public int ChildrenCount { + get { + return (children != null) ? children.Count : 0; + } + } + public StatisticalHitItemTreeNode[] Children { + get { + if (children != null) { + StatisticalHitItemTreeNode[] result = new StatisticalHitItemTreeNode [children.Count]; + int resultIndex = 0; + foreach (StatisticalHitItemTreeNode child in children.Values) { + result [resultIndex] = child; + resultIndex ++; + } + Array.Sort (result, CompareByHitCount); + return result; + } else { + return emptyChildren; + } + } + } + + public StatisticalHitItemTreeNode AddChild (IStatisticalHitItem childItem) { + if (children == null) { + children = new Dictionary<string, StatisticalHitItemTreeNode> (); + } + StatisticalHitItemTreeNode child; + if (children.ContainsKey (childItem.Name)) { + child = children [childItem.Name]; + } else { + child = new StatisticalHitItemTreeNode (childItem); + children [childItem.Name] = child; + } + child.IncrementHitCount (); + return child; + } + + public void PrintTree (TextWriter writer, uint fatherHits, int level) { + for (int i = 0; i < level; i++) { + writer.Write (" "); + } + writer.WriteLine ("{0,5:F2}% ({1}) {2}", ((((double) HitCount) / fatherHits) * 100), HitCount, Name); + foreach (StatisticalHitItemTreeNode child in Children) { + child.PrintTree (writer, HitCount, level + 1); + } + } + + public StatisticalHitItemTreeNode (IStatisticalHitItem item) { + this.item = item; + this.hitCount = 0; + this.children = null; + } + } + public class LoadedMethod : BaseLoadedMethod<LoadedClass>, IStatisticalHitItem, IHeapItemSetStatisticsSubject { ulong clicks; public ulong Clicks { |