diff options
author | Mike Kestner <mkestner@gmail.com> | 2009-06-10 01:44:01 +0400 |
---|---|---|
committer | Mike Kestner <mkestner@gmail.com> | 2009-06-10 01:44:01 +0400 |
commit | 1b513aa3f540ecd227cdffb80575d9ac204b9600 (patch) | |
tree | 3a4533caa708b574ec5cd3a521161a163245e10f | |
parent | a049cf80062dc0b4daa1514da4c4638bb488dd43 (diff) |
2009-06-09 Mike Kestner <mkestner@novell.com>
* ObjectModel.cs: commit Massi's calls StackTrace logging.
2009-06-09 Mike Kestner <mkestner@novell.com>
* Main.cs: commit Massi's new calls profile formatting code.
2009-06-09 Mike Kestner <mkestner@novell.com>
* CallsStore.cs: use StackTrace objects to navigate the call tree
and obtain context appropriate clicks info. Fix a bug in the GetIter
path traversal logic for trees deeper than 2 levels.
svn path=/trunk/mono-tools/; revision=135791
-rw-r--r-- | Mono.Profiler/Mono.Profiler.Widgets/CallsStore.cs | 33 | ||||
-rw-r--r-- | Mono.Profiler/Mono.Profiler.Widgets/ChangeLog | 6 | ||||
-rw-r--r-- | Mono.Profiler/profiler-decoder-library/ChangeLog | 3 | ||||
-rw-r--r-- | Mono.Profiler/profiler-decoder-library/ObjectModel.cs | 75 | ||||
-rw-r--r-- | Mono.Profiler/profiler-file-decoder/ChangeLog | 3 | ||||
-rw-r--r-- | Mono.Profiler/profiler-file-decoder/Main.cs | 17 |
6 files changed, 118 insertions, 19 deletions
diff --git a/Mono.Profiler/Mono.Profiler.Widgets/CallsStore.cs b/Mono.Profiler/Mono.Profiler.Widgets/CallsStore.cs index dc142a3d..457f90d7 100644 --- a/Mono.Profiler/Mono.Profiler.Widgets/CallsStore.cs +++ b/Mono.Profiler/Mono.Profiler.Widgets/CallsStore.cs @@ -11,17 +11,15 @@ namespace Mono.Profiler.Widgets { class Node { - ulong clicks; Node parent; List<Node> children; - LoadedMethod method; + StackTrace frame; GCHandle gch; - public Node (Node parent, LoadedMethod method, ulong clicks) + public Node (Node parent, StackTrace frame) { this.parent = parent; - this.method = method; - this.clicks = clicks; + this.frame = frame; gch = GCHandle.Alloc (this, GCHandleType.Weak); } @@ -29,19 +27,19 @@ namespace Mono.Profiler.Widgets { get { if (children == null) { children = new List<Node> (); - foreach (LoadedMethod.ClicksPerCalledMethod clicks in method.Methods) - children.Add (new Node (this, clicks.Method, clicks.Clicks)); + foreach (StackTrace child in frame.CalledFrames) + children.Add (new Node (this, child)); } return children; } } public ulong Clicks { - get { return clicks; } + get { return frame.Clicks; } } public LoadedMethod Method { - get { return method; } + get { return frame.TopMethod; } } public Node Parent { @@ -86,10 +84,9 @@ namespace Mono.Profiler.Widgets { return; nodes = new List<Node> (); - foreach (LoadedMethod m in data.LoadedElements.Methods) { - total_clicks += m.Clicks; - if (m.Callers.Length == 0) - nodes.Add (new Node (null, m, m.Clicks)); + foreach (StackTrace frame in StackTrace.RootFrames) { + total_clicks += frame.TopMethod.Clicks; + nodes.Add (new Node (null, frame)); } } @@ -121,14 +118,14 @@ namespace Mono.Profiler.Widgets { iter = TreeIter.Zero; if (path.Indices.Length == 0 || nodes.Count <= path.Indices [0]) return false; + Node node = nodes [path.Indices [0]]; - if (path.Indices.Length == 1) - iter = (TreeIter) node; - else { - if (node.Children.Count <= path.Indices [1]) + for (int i = 1; i < path.Indices.Length; i++) { + if (node.Children.Count <= path.Indices [i]) return false; - iter = (TreeIter) node.Children [path.Indices [1]]; + node = node.Children [path.Indices [i]]; } + iter = (TreeIter) node; return true; } diff --git a/Mono.Profiler/Mono.Profiler.Widgets/ChangeLog b/Mono.Profiler/Mono.Profiler.Widgets/ChangeLog index f346c318..18bbb9d4 100644 --- a/Mono.Profiler/Mono.Profiler.Widgets/ChangeLog +++ b/Mono.Profiler/Mono.Profiler.Widgets/ChangeLog @@ -1,3 +1,9 @@ +2009-06-09 Mike Kestner <mkestner@novell.com> + + * CallsStore.cs: use StackTrace objects to navigate the call tree + and obtain context appropriate clicks info. Fix a bug in the GetIter + path traversal logic for trees deeper than 2 levels. + 2009-05-21 Mike Kestner <mkestner@novell.com> * *: initial checkin. beginnings of a widget library for profiler diff --git a/Mono.Profiler/profiler-decoder-library/ChangeLog b/Mono.Profiler/profiler-decoder-library/ChangeLog index 6a81617c..7fbf8edb 100644 --- a/Mono.Profiler/profiler-decoder-library/ChangeLog +++ b/Mono.Profiler/profiler-decoder-library/ChangeLog @@ -1,3 +1,6 @@ +2009-06-09 Mike Kestner <mkestner@novell.com> + * ObjectModel.cs: commit Massi's calls StackTrace logging. + 2009-05-21 Mike Kestner <mkestner@novell.com> * *: replace MD 1.0 solution files with 2.0 msbuild files, and turn on makefile synchronization instead of generated makefiles. diff --git a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs index bc15c22f..fd81e498 100644 --- a/Mono.Profiler/profiler-decoder-library/ObjectModel.cs +++ b/Mono.Profiler/profiler-decoder-library/ObjectModel.cs @@ -258,6 +258,66 @@ namespace Mono.Profiler { } } + ulong clicks; + public ulong Clicks { + get { + return clicks; + } + } + uint calls; + public ulong Calls { + get { + return calls; + } + } + + public void ResetCalls () { + calls = 0; + clicks = 0; + } + public void RegisterCall (ulong clicks) { + this.clicks += clicks; + calls ++; + } + + static StackTrace[] EmptyCalledFrames = new StackTrace [0]; + List<StackTrace> calledFrames; + public StackTrace[] CalledFrames { + get { + if (calledFrames != null) { + StackTrace[] result = calledFrames.ToArray (); + Array.Sort (result, CompareByClicks); + Array.Reverse (result); + return result; + } else { + return EmptyCalledFrames; + } + } + } + void AddCalledFrame (StackTrace calledFrame) { + if (calledFrames == null) { + calledFrames = new List<StackTrace> (); + } + calledFrames.Add (calledFrame); + } + + public static Comparison<StackTrace> CompareByClicks = delegate (StackTrace a, StackTrace b) { + return a.Clicks.CompareTo (b.Clicks); + }; + public static Comparison<StackTrace> CompareByCalls = delegate (StackTrace a, StackTrace b) { + return a.Calls.CompareTo (b.Calls); + }; + + static List<StackTrace> rootFrames; + public static StackTrace[] RootFrames { + get { + StackTrace[] result = rootFrames.ToArray (); + Array.Sort (result, CompareByClicks); + Array.Reverse (result); + return result; + } + } + public void Write (TextWriter writer, int depth, string indentationString) { writer.Write ("CallStack of id "); writer.Write (id); @@ -307,8 +367,16 @@ namespace Mono.Profiler { } StackTrace (LoadedMethod topMethod, StackTrace caller, bool methodIsBeingJitted) { + this.clicks = 0; + this.calls = 0; + this.calledFrames = null; this.topMethod = topMethod; this.caller = caller; + if (caller != null) { + caller.AddCalledFrame (this); + } else { + rootFrames.Add (this); + } this.methodIsBeingJitted = methodIsBeingJitted; this.level = caller != null ? caller.level + 1 : 1; this.id = nextFreeId; @@ -344,6 +412,7 @@ namespace Mono.Profiler { static Dictionary<uint,List<StackTrace>> [] tracesByLevel; public static readonly StackTrace StackTraceUnavailable; static StackTrace () { + rootFrames = new List<StackTrace> (); nextFreeId = 0; tracesByLevel = new Dictionary<uint,List<StackTrace>> [64]; StackTraceUnavailable = NewStackTrace (CallStack.StackFrame.StackFrameUnavailable); @@ -388,7 +457,7 @@ namespace Mono.Profiler { } class CallStack { - internal class StackFrame { + public class StackFrame { LoadedMethod method; public LoadedMethod Method { get { @@ -510,6 +579,10 @@ namespace Mono.Profiler { stackTop = StackFrame.FrameFactory (method, counter, false, stackTop); } internal void MethodExit (LoadedMethod method, ulong counter) { + StackTrace trace = StackTrace.NewStackTrace (this); + if (trace != null) { + trace.RegisterCall (counter); + } PopMethod (method, counter, false); } internal void TopMethodExit (ulong counter) { diff --git a/Mono.Profiler/profiler-file-decoder/ChangeLog b/Mono.Profiler/profiler-file-decoder/ChangeLog index 532af7da..b9c658e6 100644 --- a/Mono.Profiler/profiler-file-decoder/ChangeLog +++ b/Mono.Profiler/profiler-file-decoder/ChangeLog @@ -1,3 +1,6 @@ +2009-06-09 Mike Kestner <mkestner@novell.com> + * Main.cs: commit Massi's new calls profile formatting code. + 2009-05-21 Mike Kestner <mkestner@novell.com> * *: replace MD 1.0 solution files with 2.0 msbuild files, and turn on makefile synchronization instead of generated makefiles. diff --git a/Mono.Profiler/profiler-file-decoder/Main.cs b/Mono.Profiler/profiler-file-decoder/Main.cs index ad09377a..1cd7e669 100644 --- a/Mono.Profiler/profiler-file-decoder/Main.cs +++ b/Mono.Profiler/profiler-file-decoder/Main.cs @@ -113,6 +113,18 @@ namespace Mono.Profiler } + static void PrintExecutionTimeByCallStack (TextWriter writer, ProfilerEventHandler data, StackTrace stackFrame, double callerSeconds, int indentationLevel) { + for (int i = 0; i < indentationLevel; i++) { + writer.Write (" "); + } + LoadedMethod currentMethod = stackFrame.TopMethod; + double currentSeconds = data.ClicksToSeconds (stackFrame.TopMethod.Clicks); + writer.WriteLine ("{0,5:F2}% ({1:F6}s, {2} calls) {3}.{4}", ((currentSeconds / callerSeconds) * 100), currentSeconds, stackFrame.Calls, currentMethod.Class.Name, currentMethod.Name); + foreach (StackTrace calledFrame in stackFrame.CalledFrames) { + PrintExecutionTimeByCallStack (writer, data, calledFrame, currentSeconds, indentationLevel + 1); + } + } + static void PrintData (TextWriter writer, ProfilerEventHandler data) { LoadedClass[] classes = data.LoadedElements.Classes; LoadedMethod[] methods = data.LoadedElements.Methods; @@ -160,6 +172,11 @@ namespace Mono.Profiler } } } + + writer.WriteLine ("Reporting execution time by stack frame (on {0} methods)", methods.Length); + foreach (StackTrace rootFrame in StackTrace.RootFrames) { + PrintExecutionTimeByCallStack (writer, data, rootFrame, data.ClicksToSeconds (totalExecutionClicks), 0); + } } else { writer.WriteLine ("No execution time reported (on {0} methods)", methods.Length); } |