From 4a454b5010735d9a0f138b61311c5bc9481fca03 Mon Sep 17 00:00:00 2001 From: Jon Trowbridge Date: Sun, 9 Oct 2005 18:21:15 +0000 Subject: [PATCH] Added a simple summary report, and made it the default. Finished lazy loading of backtraces and GC data. svn path=/trunk/heap-buddy/; revision=51491 --- analyzer/Backtrace.cs | 64 ++++++++++ analyzer/Frame.cs | 35 ++++++ analyzer/Gc.cs | 139 ++++----------------- analyzer/HeapBuddy.cs | 4 +- analyzer/Makefile.am | 3 + analyzer/OutfileReader.cs | 249 ++++++++++++++++++++++++++++---------- analyzer/SummaryReport.cs | 56 +++++++++ 7 files changed, 368 insertions(+), 182 deletions(-) create mode 100644 analyzer/Backtrace.cs create mode 100644 analyzer/Frame.cs create mode 100644 analyzer/SummaryReport.cs diff --git a/analyzer/Backtrace.cs b/analyzer/Backtrace.cs new file mode 100644 index 0000000..ba130dc --- /dev/null +++ b/analyzer/Backtrace.cs @@ -0,0 +1,64 @@ +// +// Backtrace.cs +// +// Copyright (C) 2005 Novell, Inc. +// + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of version 2 of the GNU General Public +// License as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +using System; + +namespace HeapBuddy { + + public class Backtrace { + + public Type Type; + + public int LastGeneration; + + public ObjectStats LastObjectStats; + + public Frame [] frames; + + uint code; + OutfileReader reader; + + public Backtrace (uint code, OutfileReader reader) + { + this.code = code; + this.reader = reader; + } + + public uint Code { + get { return code; } + } + + public Frame [] Frames { + + get { + if (frames == null) + frames = reader.GetFrames (code); + return frames; + } + + set { + frames = value; + } + } + } + +} diff --git a/analyzer/Frame.cs b/analyzer/Frame.cs new file mode 100644 index 0000000..8156b44 --- /dev/null +++ b/analyzer/Frame.cs @@ -0,0 +1,35 @@ +// +// Frame.cs +// +// Copyright (C) 2005 Novell, Inc. +// + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of version 2 of the GNU General Public +// License as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +using System; +using System.IO; + +namespace HeapBuddy { + + public struct Frame { + + public uint MethodCode; + public string MethodName; + public uint IlOffset; + } + +} diff --git a/analyzer/Gc.cs b/analyzer/Gc.cs index 916edb8..c8413c5 100644 --- a/analyzer/Gc.cs +++ b/analyzer/Gc.cs @@ -26,139 +26,48 @@ using System.IO; namespace HeapBuddy { public struct GcData { - public uint BacktraceCode; + public Backtrace Backtrace; public ObjectStats ObjectStats; } public class Gc { - private int generation; - private long time_t; - private DateTime timestamp; - private long pre_gc_live_bytes; - private long post_gc_live_bytes; + public int Generation; + + public long TimeT; + public DateTime Timestamp; + + public long PreGcLiveBytes; + public long PostGcLiveBytes; + private GcData [] gc_data; + OutfileReader reader; - public int Generation { - get { return generation; } + ///////////////////////////////////////////////////////////////// + + public Gc (OutfileReader reader) + { + this.reader = reader; } - public DateTime Timestamp { - get { return timestamp; } - } - - public long PreGcLiveBytes { - get { return pre_gc_live_bytes; } - } - - public long PostGcLiveBytes { - get { return post_gc_live_bytes; } - } + ///////////////////////////////////////////////////////////////// public long FreedBytes { - get { return pre_gc_live_bytes - post_gc_live_bytes; } + get { return PreGcLiveBytes - PostGcLiveBytes; } } public double FreedPercentage { - get { return 100.0 * FreedBytes / pre_gc_live_bytes; } + get { return 100.0 * FreedBytes / PreGcLiveBytes; } } public GcData [] GcData { - get { return gc_data; } - } - - ///////////////////////////////////////////////////////////////// - - private void ReadHead (BinaryReader reader) - { - generation = reader.ReadInt32 (); - time_t = reader.ReadInt64 (); - timestamp = Util.ConvertTimeT (time_t); - pre_gc_live_bytes = reader.ReadInt64 (); - } - - public void ReadOnlyData (BinaryReader reader) - { - int n; - n = reader.ReadInt32 (); - - gc_data = new GcData [n]; - for (int i = 0; i < n; ++i) { - gc_data [i].BacktraceCode = reader.ReadUInt32 (); - gc_data [i].ObjectStats.Read (reader); + get { + if (gc_data == null) + gc_data = reader.GetGcData (Generation); + return gc_data; } + + set { gc_data = value; } } - - public void ReadWithData (BinaryReader reader) - { - ReadHead (reader); - ReadOnlyData (reader); - post_gc_live_bytes = reader.ReadInt64 (); - } - - public void ReadWithoutData (BinaryReader reader) - { - ReadHead (reader); - post_gc_live_bytes = reader.ReadInt64 (); - } - - public void WriteWithoutData (BinaryWriter writer) - { - writer.Write (generation); - writer.Write (time_t); - writer.Write (pre_gc_live_bytes); - writer.Write (post_gc_live_bytes); - } - - public void WriteOnlyData (BinaryWriter writer) - { - combsort_gc_data (); - writer.Write (gc_data.Length); - for (int i = 0; i < gc_data.Length; ++i) { - writer.Write (gc_data [i].BacktraceCode); - gc_data [i].ObjectStats.Write (writer); - } - } - - ///////////////////////////////////////////////////////////////// - - // This is copied from mono 1.1.8.3's implementation of System.Array - - static int new_gap (int gap) - { - gap = (gap * 10) / 13; - if (gap == 9 || gap == 10) - return 11; - if (gap < 1) - return 1; - return gap; - } - - void combsort_gc_data () - { - int start = 0; - int size = gc_data.Length; - int gap = size; - while (true) { - gap = new_gap (gap); - - bool swapped = false; - int end = start + size - gap; - for (int i = start; i < end; i++) { - int j = i + gap; - if (gc_data [i].BacktraceCode > gc_data [j].BacktraceCode) { - GcData tmp; - tmp = gc_data [i]; - gc_data [i] = gc_data [j]; - gc_data [j] = tmp; - - swapped = true; - } - } - if (gap == 1 && !swapped) - break; - } - } - } } diff --git a/analyzer/HeapBuddy.cs b/analyzer/HeapBuddy.cs index 21d4044..81c3c88 100644 --- a/analyzer/HeapBuddy.cs +++ b/analyzer/HeapBuddy.cs @@ -38,7 +38,7 @@ namespace HeapBuddy { ++args_i; } - string report_name = "types"; + string report_name = "summary"; if (args_i < args.Length && Report.Exists (args [args_i])) { report_name = args [args_i]; ++args_i; @@ -54,7 +54,9 @@ namespace HeapBuddy { for (int i = args_i; i < args.Length; ++i) remaining_args [i - args_i] = args [i]; + Console.WriteLine (); report.Run (reader, remaining_args); + Console.WriteLine (); } } diff --git a/analyzer/Makefile.am b/analyzer/Makefile.am index 999e1b9..485a212 100644 --- a/analyzer/Makefile.am +++ b/analyzer/Makefile.am @@ -7,6 +7,7 @@ WRAPPER = heap-buddy REPORT_CSFILES = \ HistoryReport.cs \ + SummaryReport.cs \ TypesReport.cs CSFILES = \ @@ -15,6 +16,8 @@ CSFILES = \ Table.cs \ ObjectStats.cs \ Type.cs \ + Frame.cs \ + Backtrace.cs \ Gc.cs \ Resize.cs \ OutfileReader.cs \ diff --git a/analyzer/OutfileReader.cs b/analyzer/OutfileReader.cs index f58d406..6541659 100644 --- a/analyzer/OutfileReader.cs +++ b/analyzer/OutfileReader.cs @@ -71,22 +71,17 @@ namespace HeapBuddy { public long Position; // of the name in the summary file } - private struct Frame { - public uint MethodCode; - public uint IlOffset; + private struct RawGcData { + public uint BacktraceCode; + public ObjectStats ObjectStats; } - private struct Backtrace { - public uint TypeCode; - public Frame [] Frames; - public int LastGeneration; - public ObjectStats LastObjectStats; - public long Position; - } + string filename; Type [] types; Method [] methods; Backtrace [] backtraces; + long [] backtrace_pos; Gc [] gcs; long [] gc_pos; Resize [] resizes; @@ -97,11 +92,15 @@ namespace HeapBuddy { uint [] method_codes_old; uint [] method_codes_new; uint [] backtrace_codes; + uint [] backtrace_type_codes; + RawGcData [] [] raw_gc_data; /////////////////////////////////////////////////////////////////// public OutfileReader (string filename) { + this.filename = filename; + Stream stream; stream = new FileStream (filename, FileMode.Open, FileAccess.Read); @@ -125,6 +124,8 @@ namespace HeapBuddy { method_codes_old = new uint [n_methods]; method_codes_new = new uint [n_methods]; backtrace_codes = new uint [n_backtraces]; + backtrace_type_codes = new uint [n_backtraces]; + raw_gc_data = new RawGcData [n_gcs] []; ReadLogFile (reader); reader.Close (); @@ -146,13 +147,20 @@ namespace HeapBuddy { File.Copy (tmp_filename, filename, true /* allow overwrite */); File.Delete (tmp_filename); - // We don't need to set lazy_reader, since all - // of the data will already be in memory. + // We need to keep around the lazy_reader, since the + // GcData is not in memory. + lazy_reader = reader; } } /////////////////////////////////////////////////////////////////// + public string Filename { + get { return filename; } + } + + /////////////////////////////////////////////////////////////////// + private void Spew (string format, params object [] args) { if (Debug) { @@ -236,6 +244,7 @@ namespace HeapBuddy { types = new Type [n_types]; methods = new Method [n_methods]; backtraces = new Backtrace [n_backtraces]; + backtrace_pos = new long [n_backtraces]; gcs = new Gc [n_gcs]; gc_pos = new long [n_gcs]; resizes = new Resize [n_resizes]; @@ -411,11 +420,15 @@ namespace HeapBuddy { return; } + Backtrace backtrace; + backtrace = new Backtrace (code, this); + backtraces [i_backtrace] = backtrace; + backtrace_codes [i_backtrace] = code; - backtraces [i_backtrace].TypeCode = type_code; + backtrace_type_codes [i_backtrace] = type_code; Frame [] frames = new Frame [n_frames]; - backtraces [i_backtrace].Frames = frames; + backtrace.Frames = frames; for (int i = 0; i < n_frames; ++i) { frames [i].MethodCode = reader.ReadUInt32 (); @@ -428,10 +441,28 @@ namespace HeapBuddy { private void ReadLogFileChunk_Gc (BinaryReader reader) { Gc gc; - gc = new Gc (); - gc.ReadWithData (reader); + gc = new Gc (this); + + gc.Generation = reader.ReadInt32 (); + gc.TimeT = reader.ReadInt64 (); + gc.Timestamp = Util.ConvertTimeT (gc.TimeT); + gc.PreGcLiveBytes = reader.ReadInt64 (); + + int n; + n = reader.ReadInt32 (); + + RawGcData [] raw; + raw = new RawGcData [n]; + for (int i = 0; i < n; ++i) { + raw [i].BacktraceCode = reader.ReadUInt32 (); + raw [i].ObjectStats.Read (reader); + } + combsort_raw_gc_data (raw); + + gc.PostGcLiveBytes = reader.ReadInt64 (); gcs [i_gc] = gc; + raw_gc_data [i_gc] = raw; ++i_gc; if (gc.Generation >= 0) @@ -580,6 +611,15 @@ namespace HeapBuddy { backtrace_codes [i] = backtrace_codes [j]; backtrace_codes [j] = tmp_code; + tmp_code = backtrace_type_codes [i]; + backtrace_type_codes [i] = backtrace_type_codes [j]; + backtrace_type_codes [j] = tmp_code; + + long tmp_pos; + tmp_pos = backtrace_pos [i]; + backtrace_pos [i] = backtrace_pos [j]; + backtrace_pos [j] = tmp_pos; + Backtrace tmp; tmp = backtraces [i]; backtraces [i] = backtraces [j]; @@ -593,6 +633,32 @@ namespace HeapBuddy { } } + static void combsort_raw_gc_data (RawGcData [] data) + { + int start = 0; + int size = data.Length; + int gap = size; + while (true) { + gap = new_gap (gap); + + bool swapped = false; + int end = start + size - gap; + for (int i = start; i < end; i++) { + int j = i + gap; + if (data [i].BacktraceCode > data [j].BacktraceCode) { + RawGcData tmp; + tmp = data [i]; + data [i] = data [j]; + data [j] = tmp; + + swapped = true; + } + } + if (gap == 1 && !swapped) + break; + } + } + /////////////////////////////////////////////////////////////////// private uint TranslateTypeCode (uint code) @@ -668,18 +734,18 @@ namespace HeapBuddy { // Remap the backtrace codes in the GCs for (int i = 0; i < gcs.Length; ++i) { - for (int j = 0; j < gcs [i].GcData.Length; ++j) { + for (int j = 0; j < raw_gc_data [i].Length; ++j) { uint code; - code = gcs [i].GcData [j].BacktraceCode; + code = raw_gc_data [i] [j].BacktraceCode; code = TranslateBacktraceCode (code); - gcs [i].GcData [j].BacktraceCode = code; + raw_gc_data [i] [j].BacktraceCode = code; } } // Remap the type and method codes in the backtrace, // and replace the backtrace codes. for (int i = 0; i < backtraces.Length; ++i) { - backtraces [i].TypeCode = TranslateTypeCode (backtraces [i].TypeCode); + backtrace_type_codes [i] = TranslateTypeCode (backtrace_type_codes [i]); for (int j = 0; j < backtraces [i].Frames.Length; ++j) { uint code; code = backtraces [i].Frames [j].MethodCode; @@ -716,17 +782,20 @@ namespace HeapBuddy { count = backtraces.Length; for (int i = gcs.Length - 1; i >= 0; --i) { - for (int j = 0; j < gcs [i].GcData.Length; ++j) { + for (int j = 0; j < raw_gc_data [i].Length; ++j) { + RawGcData raw; + raw = raw_gc_data [i] [j]; + uint bt_code; - bt_code = gcs [i].GcData [j].BacktraceCode; + bt_code = raw.BacktraceCode; if (backtraces [bt_code].LastGeneration == int.MaxValue) { backtraces [bt_code].LastGeneration = gcs [i].Generation; - backtraces [bt_code].LastObjectStats = gcs [i].GcData [j].ObjectStats; + backtraces [bt_code].LastObjectStats = raw.ObjectStats; --count; // Add this backtrace to our per-type totals uint type_code; - type_code = backtraces [bt_code].TypeCode; + type_code = backtrace_type_codes [bt_code]; types [type_code].BacktraceCount++; if (types [type_code].LastGeneration == int.MaxValue) { types [type_code].LastGeneration = backtraces [bt_code].LastGeneration; @@ -747,7 +816,7 @@ namespace HeapBuddy { /////////////////////////////////////////////////////////////////// - private void ReadSummaryTableOfContents (BinaryReader reader) + private void ReadSummary_TableOfContents (BinaryReader reader) { type_name_data_offset = reader.ReadInt64 (); method_name_data_offset = reader.ReadInt64 (); @@ -760,7 +829,7 @@ namespace HeapBuddy { gc_index_offset = reader.ReadInt64 (); } - private void WriteSummaryTableOfContents (BinaryWriter writer) + private void WriteSummary_TableOfContents (BinaryWriter writer) { writer.Write (type_name_data_offset); writer.Write (method_name_data_offset); @@ -781,29 +850,23 @@ namespace HeapBuddy { private void ReadSummaryFile (BinaryReader reader) { - ReadSummaryTableOfContents (reader); - ReadSummaryIndexes (reader); - ReadSummaryTypes (reader); - ReadSummaryResizes (reader); - ReadSummaryGcs (reader); + ReadSummary_TableOfContents (reader); + ReadSummary_Methods (reader); + ReadSummary_Types (reader); + ReadSummary_Backtraces (reader); + ReadSummary_Resizes (reader); + ReadSummary_Gcs (reader); } - private void ReadSummaryIndexes (BinaryReader reader) + private void ReadSummary_Methods (BinaryReader reader) { reader.BaseStream.Seek (methods_by_code_offset, SeekOrigin.Begin); for (int i = 0; i < methods.Length; ++i) methods [i].Position = reader.ReadInt64 (); - reader.BaseStream.Seek (backtrace_index_offset, SeekOrigin.Begin); - for (int i = 0; i < backtraces.Length; ++i) { - backtraces [i].TypeCode = reader.ReadUInt32 (); - backtraces [i].LastGeneration = reader.ReadInt32 (); - backtraces [i].LastObjectStats.Read (reader); - backtraces [i].Position = reader.ReadInt64 (); - } } - private void ReadSummaryTypes (BinaryReader reader) + private void ReadSummary_Types (BinaryReader reader) { reader.BaseStream.Seek (type_name_data_offset, SeekOrigin.Begin); for (int i = 0; i < types.Length; ++i) { @@ -823,7 +886,25 @@ namespace HeapBuddy { } } - private void ReadSummaryResizes (BinaryReader reader) + private void ReadSummary_Backtraces (BinaryReader reader) + { + reader.BaseStream.Seek (backtrace_index_offset, SeekOrigin.Begin); + for (int i = 0; i < backtraces.Length; ++i) { + Backtrace backtrace; + backtrace = new Backtrace ((uint) i, this); + backtraces [i] = backtrace; + + uint type_code; + type_code = reader.ReadUInt32 (); + backtrace.Type = types [type_code]; + backtrace.LastGeneration = reader.ReadInt32 (); + backtrace.LastObjectStats.Read (reader); + backtrace_pos [i] = reader.ReadInt64 (); + } + + } + + private void ReadSummary_Resizes (BinaryReader reader) { reader.BaseStream.Seek (resize_data_offset, SeekOrigin.Begin); for (int i = 0; i < resizes.Length; ++i) { @@ -836,13 +917,19 @@ namespace HeapBuddy { } } - private void ReadSummaryGcs (BinaryReader reader) + private void ReadSummary_Gcs (BinaryReader reader) { reader.BaseStream.Seek (gc_index_offset, SeekOrigin.Begin); for (int i = 0; i < gcs.Length; ++i) { Gc gc; - gc = new Gc (); - gc.ReadWithoutData (reader); + gc = new Gc (this); + + gc.Generation = reader.ReadInt32 (); + gc.TimeT = reader.ReadInt64 (); + gc.Timestamp = Util.ConvertTimeT (gc.TimeT); + gc.PreGcLiveBytes = reader.ReadInt64 (); + gc.PostGcLiveBytes = reader.ReadInt64 (); + gcs [i] = gc; gc_pos [i] = reader.ReadInt64 (); } @@ -861,19 +948,19 @@ namespace HeapBuddy { long toc_offset; toc_offset = writer.BaseStream.Position; - WriteSummaryTableOfContents (writer); // writes placeholder data + WriteSummary_TableOfContents (writer); // writes placeholder data - WriteSummaryData (writer); + WriteSummary_Data (writer); - WriteSummaryIndexes (writer); + WriteSummary_Indexes (writer); - WriteSummaryTypes (writer); + WriteSummary_Types (writer); writer.BaseStream.Seek (toc_offset, SeekOrigin.Begin); - WriteSummaryTableOfContents (writer); // writes the actual data + WriteSummary_TableOfContents (writer); // writes the actual data } - private void WriteSummaryData (BinaryWriter writer) + private void WriteSummary_Data (BinaryWriter writer) { // Write out the name strings. type_name_data_offset = writer.BaseStream.Position; @@ -894,7 +981,7 @@ namespace HeapBuddy { // of each in the file. backtrace_data_offset = writer.BaseStream.Position; for (int i = 0; i < backtraces.Length; ++i) { - backtraces [i].Position = writer.BaseStream.Position; + backtrace_pos [i] = writer.BaseStream.Position; writer.Write (backtraces [i].Frames.Length); for (int j = 0; j < backtraces [i].Frames.Length; ++j) { writer.Write (backtraces [i].Frames [j].MethodCode); @@ -908,8 +995,14 @@ namespace HeapBuddy { gc_data_offset = writer.BaseStream.Position; for (int i = 0; i < gcs.Length; ++i) { gc_pos [i] = writer.BaseStream.Position; - gcs [i].WriteOnlyData (writer); + + writer.Write (raw_gc_data [i].Length); + for (int j = 0; j < raw_gc_data [i].Length; ++j) { + writer.Write (raw_gc_data [i] [j].BacktraceCode); + raw_gc_data [i] [j].ObjectStats.Write (writer); + } } + raw_gc_data = null; // We don't need these anymore // Write out all the resizes. @@ -918,7 +1011,7 @@ namespace HeapBuddy { resizes [i].Write (writer); } - private void WriteSummaryIndexes (BinaryWriter writer) + private void WriteSummary_Indexes (BinaryWriter writer) { methods_by_code_offset = writer.BaseStream.Position; for (int i = 0; i < methods.Length; ++i) @@ -927,20 +1020,23 @@ namespace HeapBuddy { // backtraces were sorted in WriteSummary backtrace_index_offset = writer.BaseStream.Position; for (int i = 0; i < backtraces.Length; ++i) { - writer.Write (backtraces [i].TypeCode); + writer.Write (backtrace_type_codes [i]); writer.Write (backtraces [i].LastGeneration); backtraces [i].LastObjectStats.Write (writer); - writer.Write (backtraces [i].Position); + writer.Write (backtrace_pos [i]); } gc_index_offset = writer.BaseStream.Position; for (int i = 0; i < gcs.Length; ++i) { - gcs [i].WriteWithoutData (writer); + writer.Write (gcs [i].Generation); + writer.Write (gcs [i].TimeT); + writer.Write (gcs [i].PreGcLiveBytes); + writer.Write (gcs [i].PostGcLiveBytes); writer.Write (gc_pos [i]); } } - private void WriteSummaryTypes (BinaryWriter writer) + private void WriteSummary_Types (BinaryWriter writer) { types_by_code_offset = writer.BaseStream.Position; for (int i = 0; i < types.Length; ++i) { @@ -962,6 +1058,10 @@ namespace HeapBuddy { get { return gcs; } } + public Backtrace [] Backtraces { + get { return backtraces; } + } + /////////////////////////////////////////////////////////////////// public Type [] Types { @@ -991,7 +1091,7 @@ namespace HeapBuddy { /////////////////////////////////////////////////////////////////// - public string GetMethodName (uint code) + private string GetMethodName (uint code) { if (methods [code].Name == null) { lazy_reader.BaseStream.Seek (methods [code].Position, SeekOrigin.Begin); @@ -1001,13 +1101,9 @@ namespace HeapBuddy { return methods [code].Name; } -#if false - private void PopulateBacktrace (uint code) + public Frame [] GetFrames (uint backtrace_code) { - if (backtraces [code].Frames != null) - return; - - lazy_reader.BaseStream.Seek (backtraces [code].Position, SeekOrigin.Begin); + lazy_reader.BaseStream.Seek (backtrace_pos [backtrace_code], SeekOrigin.Begin); int length; length = lazy_reader.ReadInt32 (); @@ -1019,8 +1115,29 @@ namespace HeapBuddy { frames [i].IlOffset = lazy_reader.ReadUInt32 (); } - backtraces [code].Frames = frames; + for (int i = 0; i < length; ++i) + frames [i].MethodName = GetMethodName (frames [i].MethodCode); + + return frames; + } + + public GcData [] GetGcData (int generation) + { + lazy_reader.BaseStream.Seek (gc_pos [generation], SeekOrigin.Begin); + + int length; + length = lazy_reader.ReadInt32 (); + + GcData [] gc_data; + gc_data = new GcData [length]; + for (int i = 0; i < length; ++i) { + uint bt_code; + bt_code = lazy_reader.ReadUInt32 (); + gc_data [i].Backtrace = backtraces [bt_code]; + gc_data [i].ObjectStats.Read (lazy_reader); + } + + return gc_data; } -#endif } } diff --git a/analyzer/SummaryReport.cs b/analyzer/SummaryReport.cs new file mode 100644 index 0000000..8de02ec --- /dev/null +++ b/analyzer/SummaryReport.cs @@ -0,0 +1,56 @@ +// +// SummaryReport.cs +// +// Copyright (C) 2005 Novell, Inc. +// + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of version 2 of the GNU General Public +// License as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +using System; +using System.Collections; +using System.IO; + +namespace HeapBuddy { + + public class SummaryReport : Report { + + public SummaryReport () : base ("Summary") { } + + override public void Run (OutfileReader reader, string [] args) + { + Table table; + table = new Table (); + + table.AddRow ("SUMMARY", ""); + table.AddRow ("", ""); + + table.AddRow ("Filename:", reader.Filename); + table.AddRow ("GCs:", reader.Gcs.Length); + table.AddRow ("Resizes:", reader.Resizes.Length); + table.AddRow ("Final heap size:", Util.PrettySize (reader.Resizes [reader.Resizes.Length-1].NewSize)); + + table.AddRow ("", ""); + + table.AddRow ("Allocated Types:", reader.Types.Length); + table.AddRow ("Backtraces:", reader.Backtraces.Length); + + table.SetAlignment (1, Alignment.Left); + + Console.WriteLine (table); + } + } +}