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
This commit is contained in:
Родитель
308d08f570
Коммит
4a454b5010
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
139
analyzer/Gc.cs
139
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче