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 {
|
namespace HeapBuddy {
|
||||||
|
|
||||||
public struct GcData {
|
public struct GcData {
|
||||||
public uint BacktraceCode;
|
public Backtrace Backtrace;
|
||||||
public ObjectStats ObjectStats;
|
public ObjectStats ObjectStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Gc {
|
public class Gc {
|
||||||
|
|
||||||
private int generation;
|
public int Generation;
|
||||||
private long time_t;
|
|
||||||
private DateTime timestamp;
|
public long TimeT;
|
||||||
private long pre_gc_live_bytes;
|
public DateTime Timestamp;
|
||||||
private long post_gc_live_bytes;
|
|
||||||
|
public long PreGcLiveBytes;
|
||||||
|
public long PostGcLiveBytes;
|
||||||
|
|
||||||
private GcData [] gc_data;
|
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 {
|
public long FreedBytes {
|
||||||
get { return pre_gc_live_bytes - post_gc_live_bytes; }
|
get { return PreGcLiveBytes - PostGcLiveBytes; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double FreedPercentage {
|
public double FreedPercentage {
|
||||||
get { return 100.0 * FreedBytes / pre_gc_live_bytes; }
|
get { return 100.0 * FreedBytes / PreGcLiveBytes; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public GcData [] GcData {
|
public GcData [] GcData {
|
||||||
get { return gc_data; }
|
get {
|
||||||
}
|
if (gc_data == null)
|
||||||
|
gc_data = reader.GetGcData (Generation);
|
||||||
/////////////////////////////////////////////////////////////////
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
++args_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
string report_name = "types";
|
string report_name = "summary";
|
||||||
if (args_i < args.Length && Report.Exists (args [args_i])) {
|
if (args_i < args.Length && Report.Exists (args [args_i])) {
|
||||||
report_name = args [args_i];
|
report_name = args [args_i];
|
||||||
++args_i;
|
++args_i;
|
||||||
|
@ -54,7 +54,9 @@ namespace HeapBuddy {
|
||||||
for (int i = args_i; i < args.Length; ++i)
|
for (int i = args_i; i < args.Length; ++i)
|
||||||
remaining_args [i - args_i] = args [i];
|
remaining_args [i - args_i] = args [i];
|
||||||
|
|
||||||
|
Console.WriteLine ();
|
||||||
report.Run (reader, remaining_args);
|
report.Run (reader, remaining_args);
|
||||||
|
Console.WriteLine ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ WRAPPER = heap-buddy
|
||||||
|
|
||||||
REPORT_CSFILES = \
|
REPORT_CSFILES = \
|
||||||
HistoryReport.cs \
|
HistoryReport.cs \
|
||||||
|
SummaryReport.cs \
|
||||||
TypesReport.cs
|
TypesReport.cs
|
||||||
|
|
||||||
CSFILES = \
|
CSFILES = \
|
||||||
|
@ -15,6 +16,8 @@ CSFILES = \
|
||||||
Table.cs \
|
Table.cs \
|
||||||
ObjectStats.cs \
|
ObjectStats.cs \
|
||||||
Type.cs \
|
Type.cs \
|
||||||
|
Frame.cs \
|
||||||
|
Backtrace.cs \
|
||||||
Gc.cs \
|
Gc.cs \
|
||||||
Resize.cs \
|
Resize.cs \
|
||||||
OutfileReader.cs \
|
OutfileReader.cs \
|
||||||
|
|
|
@ -71,22 +71,17 @@ namespace HeapBuddy {
|
||||||
public long Position; // of the name in the summary file
|
public long Position; // of the name in the summary file
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Frame {
|
private struct RawGcData {
|
||||||
public uint MethodCode;
|
public uint BacktraceCode;
|
||||||
public uint IlOffset;
|
public ObjectStats ObjectStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Backtrace {
|
string filename;
|
||||||
public uint TypeCode;
|
|
||||||
public Frame [] Frames;
|
|
||||||
public int LastGeneration;
|
|
||||||
public ObjectStats LastObjectStats;
|
|
||||||
public long Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type [] types;
|
Type [] types;
|
||||||
Method [] methods;
|
Method [] methods;
|
||||||
Backtrace [] backtraces;
|
Backtrace [] backtraces;
|
||||||
|
long [] backtrace_pos;
|
||||||
Gc [] gcs;
|
Gc [] gcs;
|
||||||
long [] gc_pos;
|
long [] gc_pos;
|
||||||
Resize [] resizes;
|
Resize [] resizes;
|
||||||
|
@ -97,11 +92,15 @@ namespace HeapBuddy {
|
||||||
uint [] method_codes_old;
|
uint [] method_codes_old;
|
||||||
uint [] method_codes_new;
|
uint [] method_codes_new;
|
||||||
uint [] backtrace_codes;
|
uint [] backtrace_codes;
|
||||||
|
uint [] backtrace_type_codes;
|
||||||
|
RawGcData [] [] raw_gc_data;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public OutfileReader (string filename)
|
public OutfileReader (string filename)
|
||||||
{
|
{
|
||||||
|
this.filename = filename;
|
||||||
|
|
||||||
Stream stream;
|
Stream stream;
|
||||||
stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
|
stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
|
||||||
|
|
||||||
|
@ -125,6 +124,8 @@ namespace HeapBuddy {
|
||||||
method_codes_old = new uint [n_methods];
|
method_codes_old = new uint [n_methods];
|
||||||
method_codes_new = new uint [n_methods];
|
method_codes_new = new uint [n_methods];
|
||||||
backtrace_codes = new uint [n_backtraces];
|
backtrace_codes = new uint [n_backtraces];
|
||||||
|
backtrace_type_codes = new uint [n_backtraces];
|
||||||
|
raw_gc_data = new RawGcData [n_gcs] [];
|
||||||
|
|
||||||
ReadLogFile (reader);
|
ReadLogFile (reader);
|
||||||
reader.Close ();
|
reader.Close ();
|
||||||
|
@ -146,13 +147,20 @@ namespace HeapBuddy {
|
||||||
File.Copy (tmp_filename, filename, true /* allow overwrite */);
|
File.Copy (tmp_filename, filename, true /* allow overwrite */);
|
||||||
File.Delete (tmp_filename);
|
File.Delete (tmp_filename);
|
||||||
|
|
||||||
// We don't need to set lazy_reader, since all
|
// We need to keep around the lazy_reader, since the
|
||||||
// of the data will already be in memory.
|
// GcData is not in memory.
|
||||||
|
lazy_reader = reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public string Filename {
|
||||||
|
get { return filename; }
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void Spew (string format, params object [] args)
|
private void Spew (string format, params object [] args)
|
||||||
{
|
{
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
|
@ -236,6 +244,7 @@ namespace HeapBuddy {
|
||||||
types = new Type [n_types];
|
types = new Type [n_types];
|
||||||
methods = new Method [n_methods];
|
methods = new Method [n_methods];
|
||||||
backtraces = new Backtrace [n_backtraces];
|
backtraces = new Backtrace [n_backtraces];
|
||||||
|
backtrace_pos = new long [n_backtraces];
|
||||||
gcs = new Gc [n_gcs];
|
gcs = new Gc [n_gcs];
|
||||||
gc_pos = new long [n_gcs];
|
gc_pos = new long [n_gcs];
|
||||||
resizes = new Resize [n_resizes];
|
resizes = new Resize [n_resizes];
|
||||||
|
@ -411,11 +420,15 @@ namespace HeapBuddy {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Backtrace backtrace;
|
||||||
|
backtrace = new Backtrace (code, this);
|
||||||
|
backtraces [i_backtrace] = backtrace;
|
||||||
|
|
||||||
backtrace_codes [i_backtrace] = code;
|
backtrace_codes [i_backtrace] = code;
|
||||||
backtraces [i_backtrace].TypeCode = type_code;
|
backtrace_type_codes [i_backtrace] = type_code;
|
||||||
|
|
||||||
Frame [] frames = new Frame [n_frames];
|
Frame [] frames = new Frame [n_frames];
|
||||||
backtraces [i_backtrace].Frames = frames;
|
backtrace.Frames = frames;
|
||||||
|
|
||||||
for (int i = 0; i < n_frames; ++i) {
|
for (int i = 0; i < n_frames; ++i) {
|
||||||
frames [i].MethodCode = reader.ReadUInt32 ();
|
frames [i].MethodCode = reader.ReadUInt32 ();
|
||||||
|
@ -428,10 +441,28 @@ namespace HeapBuddy {
|
||||||
private void ReadLogFileChunk_Gc (BinaryReader reader)
|
private void ReadLogFileChunk_Gc (BinaryReader reader)
|
||||||
{
|
{
|
||||||
Gc gc;
|
Gc gc;
|
||||||
gc = new Gc ();
|
gc = new Gc (this);
|
||||||
gc.ReadWithData (reader);
|
|
||||||
|
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;
|
gcs [i_gc] = gc;
|
||||||
|
raw_gc_data [i_gc] = raw;
|
||||||
++i_gc;
|
++i_gc;
|
||||||
|
|
||||||
if (gc.Generation >= 0)
|
if (gc.Generation >= 0)
|
||||||
|
@ -580,6 +611,15 @@ namespace HeapBuddy {
|
||||||
backtrace_codes [i] = backtrace_codes [j];
|
backtrace_codes [i] = backtrace_codes [j];
|
||||||
backtrace_codes [j] = tmp_code;
|
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;
|
Backtrace tmp;
|
||||||
tmp = backtraces [i];
|
tmp = backtraces [i];
|
||||||
backtraces [i] = backtraces [j];
|
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)
|
private uint TranslateTypeCode (uint code)
|
||||||
|
@ -668,18 +734,18 @@ namespace HeapBuddy {
|
||||||
|
|
||||||
// Remap the backtrace codes in the GCs
|
// Remap the backtrace codes in the GCs
|
||||||
for (int i = 0; i < gcs.Length; ++i) {
|
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;
|
uint code;
|
||||||
code = gcs [i].GcData [j].BacktraceCode;
|
code = raw_gc_data [i] [j].BacktraceCode;
|
||||||
code = TranslateBacktraceCode (code);
|
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,
|
// Remap the type and method codes in the backtrace,
|
||||||
// and replace the backtrace codes.
|
// and replace the backtrace codes.
|
||||||
for (int i = 0; i < backtraces.Length; ++i) {
|
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) {
|
for (int j = 0; j < backtraces [i].Frames.Length; ++j) {
|
||||||
uint code;
|
uint code;
|
||||||
code = backtraces [i].Frames [j].MethodCode;
|
code = backtraces [i].Frames [j].MethodCode;
|
||||||
|
@ -716,17 +782,20 @@ namespace HeapBuddy {
|
||||||
count = backtraces.Length;
|
count = backtraces.Length;
|
||||||
|
|
||||||
for (int i = gcs.Length - 1; i >= 0; --i) {
|
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;
|
uint bt_code;
|
||||||
bt_code = gcs [i].GcData [j].BacktraceCode;
|
bt_code = raw.BacktraceCode;
|
||||||
if (backtraces [bt_code].LastGeneration == int.MaxValue) {
|
if (backtraces [bt_code].LastGeneration == int.MaxValue) {
|
||||||
backtraces [bt_code].LastGeneration = gcs [i].Generation;
|
backtraces [bt_code].LastGeneration = gcs [i].Generation;
|
||||||
backtraces [bt_code].LastObjectStats = gcs [i].GcData [j].ObjectStats;
|
backtraces [bt_code].LastObjectStats = raw.ObjectStats;
|
||||||
--count;
|
--count;
|
||||||
|
|
||||||
// Add this backtrace to our per-type totals
|
// Add this backtrace to our per-type totals
|
||||||
uint type_code;
|
uint type_code;
|
||||||
type_code = backtraces [bt_code].TypeCode;
|
type_code = backtrace_type_codes [bt_code];
|
||||||
types [type_code].BacktraceCount++;
|
types [type_code].BacktraceCount++;
|
||||||
if (types [type_code].LastGeneration == int.MaxValue) {
|
if (types [type_code].LastGeneration == int.MaxValue) {
|
||||||
types [type_code].LastGeneration = backtraces [bt_code].LastGeneration;
|
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 ();
|
type_name_data_offset = reader.ReadInt64 ();
|
||||||
method_name_data_offset = reader.ReadInt64 ();
|
method_name_data_offset = reader.ReadInt64 ();
|
||||||
|
@ -760,7 +829,7 @@ namespace HeapBuddy {
|
||||||
gc_index_offset = reader.ReadInt64 ();
|
gc_index_offset = reader.ReadInt64 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteSummaryTableOfContents (BinaryWriter writer)
|
private void WriteSummary_TableOfContents (BinaryWriter writer)
|
||||||
{
|
{
|
||||||
writer.Write (type_name_data_offset);
|
writer.Write (type_name_data_offset);
|
||||||
writer.Write (method_name_data_offset);
|
writer.Write (method_name_data_offset);
|
||||||
|
@ -781,29 +850,23 @@ namespace HeapBuddy {
|
||||||
|
|
||||||
private void ReadSummaryFile (BinaryReader reader)
|
private void ReadSummaryFile (BinaryReader reader)
|
||||||
{
|
{
|
||||||
ReadSummaryTableOfContents (reader);
|
ReadSummary_TableOfContents (reader);
|
||||||
ReadSummaryIndexes (reader);
|
ReadSummary_Methods (reader);
|
||||||
ReadSummaryTypes (reader);
|
ReadSummary_Types (reader);
|
||||||
ReadSummaryResizes (reader);
|
ReadSummary_Backtraces (reader);
|
||||||
ReadSummaryGcs (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);
|
reader.BaseStream.Seek (methods_by_code_offset, SeekOrigin.Begin);
|
||||||
for (int i = 0; i < methods.Length; ++i)
|
for (int i = 0; i < methods.Length; ++i)
|
||||||
methods [i].Position = reader.ReadInt64 ();
|
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);
|
reader.BaseStream.Seek (type_name_data_offset, SeekOrigin.Begin);
|
||||||
for (int i = 0; i < types.Length; ++i) {
|
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);
|
reader.BaseStream.Seek (resize_data_offset, SeekOrigin.Begin);
|
||||||
for (int i = 0; i < resizes.Length; ++i) {
|
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);
|
reader.BaseStream.Seek (gc_index_offset, SeekOrigin.Begin);
|
||||||
for (int i = 0; i < gcs.Length; ++i) {
|
for (int i = 0; i < gcs.Length; ++i) {
|
||||||
Gc gc;
|
Gc gc;
|
||||||
gc = new Gc ();
|
gc = new Gc (this);
|
||||||
gc.ReadWithoutData (reader);
|
|
||||||
|
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;
|
gcs [i] = gc;
|
||||||
gc_pos [i] = reader.ReadInt64 ();
|
gc_pos [i] = reader.ReadInt64 ();
|
||||||
}
|
}
|
||||||
|
@ -861,19 +948,19 @@ namespace HeapBuddy {
|
||||||
|
|
||||||
long toc_offset;
|
long toc_offset;
|
||||||
toc_offset = writer.BaseStream.Position;
|
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);
|
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.
|
// Write out the name strings.
|
||||||
type_name_data_offset = writer.BaseStream.Position;
|
type_name_data_offset = writer.BaseStream.Position;
|
||||||
|
@ -894,7 +981,7 @@ namespace HeapBuddy {
|
||||||
// of each in the file.
|
// of each in the file.
|
||||||
backtrace_data_offset = writer.BaseStream.Position;
|
backtrace_data_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < backtraces.Length; ++i) {
|
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);
|
writer.Write (backtraces [i].Frames.Length);
|
||||||
for (int j = 0; j < backtraces [i].Frames.Length; ++j) {
|
for (int j = 0; j < backtraces [i].Frames.Length; ++j) {
|
||||||
writer.Write (backtraces [i].Frames [j].MethodCode);
|
writer.Write (backtraces [i].Frames [j].MethodCode);
|
||||||
|
@ -908,8 +995,14 @@ namespace HeapBuddy {
|
||||||
gc_data_offset = writer.BaseStream.Position;
|
gc_data_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < gcs.Length; ++i) {
|
for (int i = 0; i < gcs.Length; ++i) {
|
||||||
gc_pos [i] = writer.BaseStream.Position;
|
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.
|
// Write out all the resizes.
|
||||||
|
@ -918,7 +1011,7 @@ namespace HeapBuddy {
|
||||||
resizes [i].Write (writer);
|
resizes [i].Write (writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteSummaryIndexes (BinaryWriter writer)
|
private void WriteSummary_Indexes (BinaryWriter writer)
|
||||||
{
|
{
|
||||||
methods_by_code_offset = writer.BaseStream.Position;
|
methods_by_code_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < methods.Length; ++i)
|
for (int i = 0; i < methods.Length; ++i)
|
||||||
|
@ -927,20 +1020,23 @@ namespace HeapBuddy {
|
||||||
// backtraces were sorted in WriteSummary
|
// backtraces were sorted in WriteSummary
|
||||||
backtrace_index_offset = writer.BaseStream.Position;
|
backtrace_index_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < backtraces.Length; ++i) {
|
for (int i = 0; i < backtraces.Length; ++i) {
|
||||||
writer.Write (backtraces [i].TypeCode);
|
writer.Write (backtrace_type_codes [i]);
|
||||||
writer.Write (backtraces [i].LastGeneration);
|
writer.Write (backtraces [i].LastGeneration);
|
||||||
backtraces [i].LastObjectStats.Write (writer);
|
backtraces [i].LastObjectStats.Write (writer);
|
||||||
writer.Write (backtraces [i].Position);
|
writer.Write (backtrace_pos [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gc_index_offset = writer.BaseStream.Position;
|
gc_index_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < gcs.Length; ++i) {
|
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]);
|
writer.Write (gc_pos [i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteSummaryTypes (BinaryWriter writer)
|
private void WriteSummary_Types (BinaryWriter writer)
|
||||||
{
|
{
|
||||||
types_by_code_offset = writer.BaseStream.Position;
|
types_by_code_offset = writer.BaseStream.Position;
|
||||||
for (int i = 0; i < types.Length; ++i) {
|
for (int i = 0; i < types.Length; ++i) {
|
||||||
|
@ -962,6 +1058,10 @@ namespace HeapBuddy {
|
||||||
get { return gcs; }
|
get { return gcs; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Backtrace [] Backtraces {
|
||||||
|
get { return backtraces; }
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Type [] Types {
|
public Type [] Types {
|
||||||
|
@ -991,7 +1091,7 @@ namespace HeapBuddy {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public string GetMethodName (uint code)
|
private string GetMethodName (uint code)
|
||||||
{
|
{
|
||||||
if (methods [code].Name == null) {
|
if (methods [code].Name == null) {
|
||||||
lazy_reader.BaseStream.Seek (methods [code].Position, SeekOrigin.Begin);
|
lazy_reader.BaseStream.Seek (methods [code].Position, SeekOrigin.Begin);
|
||||||
|
@ -1001,13 +1101,9 @@ namespace HeapBuddy {
|
||||||
return methods [code].Name;
|
return methods [code].Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if false
|
public Frame [] GetFrames (uint backtrace_code)
|
||||||
private void PopulateBacktrace (uint code)
|
|
||||||
{
|
{
|
||||||
if (backtraces [code].Frames != null)
|
lazy_reader.BaseStream.Seek (backtrace_pos [backtrace_code], SeekOrigin.Begin);
|
||||||
return;
|
|
||||||
|
|
||||||
lazy_reader.BaseStream.Seek (backtraces [code].Position, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
length = lazy_reader.ReadInt32 ();
|
length = lazy_reader.ReadInt32 ();
|
||||||
|
@ -1019,8 +1115,29 @@ namespace HeapBuddy {
|
||||||
frames [i].IlOffset = lazy_reader.ReadUInt32 ();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче