diff options
author | Massimiliano Mantione <massi@mono-cvs.ximian.com> | 2008-10-10 18:20:49 +0400 |
---|---|---|
committer | Massimiliano Mantione <massi@mono-cvs.ximian.com> | 2008-10-10 18:20:49 +0400 |
commit | 18bb270bd047c29282fe321efb60608caf3ec0b7 (patch) | |
tree | 55855e6af450cb84b9ade76bb9d469517560c262 /Mono.Profiler | |
parent | 73b0c1958f596be55064326243c3fcf08587e7d1 (diff) |
Added support for handling the stack trace of each allocation event.
svn path=/trunk/mono-tools/; revision=115435
Diffstat (limited to 'Mono.Profiler')
-rw-r--r-- | Mono.Profiler/profiler-file-decoder/ChangeLog | 5 | ||||
-rw-r--r-- | Mono.Profiler/profiler-file-decoder/Main.cs | 105 |
2 files changed, 88 insertions, 22 deletions
diff --git a/Mono.Profiler/profiler-file-decoder/ChangeLog b/Mono.Profiler/profiler-file-decoder/ChangeLog index 899f523a..9153e585 100644 --- a/Mono.Profiler/profiler-file-decoder/ChangeLog +++ b/Mono.Profiler/profiler-file-decoder/ChangeLog @@ -1,3 +1,8 @@ +2008-10-10 Massimiliano Mantione <massi@ximian.com> + * Main.cs: + - Added support for handling the stack trace of each allocation event. + - Transferred handling of decoder bugs to the DebugProfilerEventHandler. + 2008-08-21 Massimiliano Mantione <massi@ximian.com> * Main.cs: Added support for correct accounting of allocations which happened at JIT time. diff --git a/Mono.Profiler/profiler-file-decoder/Main.cs b/Mono.Profiler/profiler-file-decoder/Main.cs index bafabe6c..fd28700e 100644 --- a/Mono.Profiler/profiler-file-decoder/Main.cs +++ b/Mono.Profiler/profiler-file-decoder/Main.cs @@ -35,6 +35,84 @@ namespace Mono.Profiler writer.WriteLine ("\n\n------------------------------------------------"); } + static void PrintMethodAllocationsPerClass (TextWriter writer, LoadedClass.AllocationsPerMethod allocationsPerMethod, bool JitTime, bool printStackTraces, double stackTraceTreshold) { + if (! JitTime) { + writer.WriteLine (" {0} bytes ({1} instances) from {2}.{3}", allocationsPerMethod.AllocatedBytes, allocationsPerMethod.AllocatedInstances, allocationsPerMethod.Method.Class.Name, allocationsPerMethod.Method.Name); + } else { + writer.WriteLine (" {0} bytes ({1} instances) at JIT time in {2}.{3}", allocationsPerMethod.AllocatedBytes, allocationsPerMethod.AllocatedInstances, allocationsPerMethod.Method.Class.Name, allocationsPerMethod.Method.Name); + } + + if (printStackTraces) { + LoadedClass.AllocationsPerStackTrace [] stackTraces = allocationsPerMethod.StackTraces; + Array.Sort (stackTraces, LoadedClass.AllocationsPerStackTrace.CompareByAllocatedBytes); + Array.Reverse (stackTraces); + double cumulativeAllocatedBytesPerStackTrace = 0; + + foreach (LoadedClass.AllocationsPerStackTrace trace in stackTraces) { + if (cumulativeAllocatedBytesPerStackTrace / allocationsPerMethod.AllocatedBytes < stackTraceTreshold) { + writer.WriteLine (" {0} bytes ({1} instances) inside", trace.AllocatedBytes, trace.AllocatedInstances); + for (StackTrace frame = trace.Trace; frame != null; frame = frame.Caller) { + writer.Write (" "); + if (frame.MethodIsBeingJitted) { + writer.Write ("[JIT time]:"); + } + writer.WriteLine ("{0}.{1}", frame.TopMethod.Class.Name, frame.TopMethod.Name); + } + } else { + break; + } + cumulativeAllocatedBytesPerStackTrace += (double)trace.AllocatedBytes; + } + } + } + + static void PrintClassAllocationData (TextWriter writer, ProfilerEventHandler data, LoadedClass c, ulong totalAllocatedBytes) { + double allocatedBytesPerClass = (double)c.AllocatedBytes; + writer.WriteLine ("{0,5:F2}% ({1} bytes) {2}", ((allocatedBytesPerClass / totalAllocatedBytes) * 100), c.AllocatedBytes, c.Name); + + if (data.Directives.AllocationsHaveStackTrace) { + LoadedClass.AllocationsPerMethod[] allocationsPerMethodArray = c.Methods; + double cumulativeAllocatedBytesPerMethod = 0; + + if (c.MethodsAtJitTimeCount > 0) { + LoadedClass.AllocationsPerMethod[] allocationsPerMethodAtJitTime = c.MethodsAtJitTime; + LoadedClass.AllocationsPerMethod[] totalAllocationsPerMethod = new LoadedClass.AllocationsPerMethod [allocationsPerMethodArray.Length + allocationsPerMethodAtJitTime.Length]; + Array.Copy (allocationsPerMethodArray, totalAllocationsPerMethod, allocationsPerMethodArray.Length); + Array.Copy (allocationsPerMethodAtJitTime, 0, totalAllocationsPerMethod, allocationsPerMethodArray.Length, allocationsPerMethodAtJitTime.Length); + allocationsPerMethodArray = totalAllocationsPerMethod; + } + + if (allocationsPerMethodArray.Length != 0) { + Array.Sort (allocationsPerMethodArray, LoadedClass.AllocationsPerMethod.CompareByAllocatedBytes); + Array.Reverse (allocationsPerMethodArray); + + foreach (LoadedClass.AllocationsPerMethod allocationsPerMethod in allocationsPerMethodArray) { + PrintMethodAllocationsPerClass (writer, allocationsPerMethod, false, cumulativeAllocatedBytesPerMethod < allocatedBytesPerClass * 0.7, 0.7); + cumulativeAllocatedBytesPerMethod += (double)allocationsPerMethod.AllocatedBytes; + } + } + } else { + LoadedClass.AllocationsPerMethod[] allocationsPerMethodArray = c.Methods; + if (allocationsPerMethodArray.Length != 0) { + Array.Sort (allocationsPerMethodArray, LoadedClass.AllocationsPerMethod.CompareByAllocatedBytes); + Array.Reverse (allocationsPerMethodArray); + + foreach (LoadedClass.AllocationsPerMethod allocationsPerMethod in allocationsPerMethodArray) { + PrintMethodAllocationsPerClass (writer, allocationsPerMethod, false, false, 0); + } + } + if (c.MethodsAtJitTimeCount > 0) { + allocationsPerMethodArray = c.MethodsAtJitTime; + Array.Sort (allocationsPerMethodArray, LoadedClass.AllocationsPerMethod.CompareByAllocatedBytes); + Array.Reverse (allocationsPerMethodArray); + foreach (LoadedClass.AllocationsPerMethod allocationsPerMethod in allocationsPerMethodArray) { + PrintMethodAllocationsPerClass (writer, allocationsPerMethod, true, false, 0); + } + } + } + + } + static void PrintData (TextWriter writer, ProfilerEventHandler data) { LoadedClass[] classes = data.LoadedElements.Classes; LoadedMethod[] methods = data.LoadedElements.Methods; @@ -52,23 +130,7 @@ namespace Mono.Profiler writer.WriteLine ("Reporting allocations (on {0} classes)", classes.Length); foreach (LoadedClass c in classes) { if (c.AllocatedBytes > 0) { - writer.WriteLine ("{0,5:F2}% ({1} bytes) {2}", ((((double)c.AllocatedBytes) / totalAllocatedBytes) * 100), c.AllocatedBytes, c.Name); - LoadedClass.AllocationsPerMethod[] allocationsPerMethodArray = c.Methods; - if (allocationsPerMethodArray.Length != 0) { - Array.Sort (allocationsPerMethodArray, LoadedClass.AllocationsPerMethod.CompareByAllocatedBytes); - Array.Reverse (allocationsPerMethodArray); - foreach (LoadedClass.AllocationsPerMethod allocationsPerMethod in allocationsPerMethodArray) { - writer.WriteLine (" {0} bytes ({1} instances) from {2}.{3}", allocationsPerMethod.AllocatedBytes, allocationsPerMethod.AllocatedInstances, allocationsPerMethod.Method.Class.Name, allocationsPerMethod.Method.Name); - } - } - if (c.MethodsAtJitTimeCount > 0) { - allocationsPerMethodArray = c.MethodsAtJitTime; - Array.Sort (allocationsPerMethodArray, LoadedClass.AllocationsPerMethod.CompareByAllocatedBytes); - Array.Reverse (allocationsPerMethodArray); - foreach (LoadedClass.AllocationsPerMethod allocationsPerMethod in allocationsPerMethodArray) { - writer.WriteLine (" {0} bytes ({1} instances) at JIT time of {2}.{3}", allocationsPerMethod.AllocatedBytes, allocationsPerMethod.AllocatedInstances, allocationsPerMethod.Method.Class.Name, allocationsPerMethod.Method.Name); - } - } + PrintClassAllocationData (writer, data, c, totalAllocatedBytes); } } } else { @@ -254,13 +316,12 @@ namespace Mono.Profiler ProfilerEventHandler data = new ProfilerEventHandler (); data.LoadedElements.RecordHeapSnapshots = false; while (! reader.HasEnded) { + BlockData currentBlock = null; try { - reader.ReadBlock ().Decode (data, reader); + currentBlock = reader.ReadBlock (); + currentBlock.Decode (data, reader); } catch (DecodingException e) { - Console.WriteLine ("WARNING: DecodingException in block of code {0}, length {1}, file offset {2}, block offset {3}: {4}", e.FailingData.Code, e.FailingData.Length, e.FailingData.FileOffset, e.OffsetInBlock, e.Message); - Console.WriteLine (e.StackTrace); - Console.WriteLine ("Original stack trace:"); - Console.WriteLine (e.InnerException.StackTrace); + Console.WriteLine ("Stopping decoding after a DecodingException in block of code {0}, length {1}, file offset {2}, block offset {3}: {4}", e.FailingData.Code, e.FailingData.Length, e.FailingData.FileOffset, e.OffsetInBlock, e.Message); break; } } |