Bug 745034 - Add page fault counts to GC statistics (r=terrence,dmandelin)

This commit is contained in:
Bill McCloskey
2012-04-09 12:30:33 -07:00
parent 55f0e8bdfc
commit 23ca606b60
5 changed files with 110 additions and 37 deletions

View File

@@ -49,6 +49,7 @@
#include "jsutil.h"
#include "prmjtime.h"
#include "gc/Memory.h"
#include "gc/Statistics.h"
#include "gc/Barrier-inl.h"
@@ -124,7 +125,7 @@ class StatisticsSerializer
if (needComma_)
pJSON(", ");
if (asJSON_ && name) {
putQuoted(name);
putKey(name);
pJSON(": ");
}
pJSON("{");
@@ -141,7 +142,7 @@ class StatisticsSerializer
if (needComma_)
pJSON(", ");
if (asJSON_)
putQuoted(name);
putKey(name);
pJSON(": [");
needComma_ = false;
}
@@ -289,32 +290,53 @@ t(int64_t t)
return double(t) / PRMJ_USEC_PER_MSEC;
}
struct PhaseInfo
{
unsigned index;
const char *name;
};
static PhaseInfo phases[] = {
{ PHASE_GC_BEGIN, "Begin Callback" },
{ PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread" },
{ PHASE_PURGE, "Purge" },
{ PHASE_MARK, "Mark" },
{ PHASE_MARK_ROOTS, "Mark Roots" },
{ PHASE_MARK_DELAYED, "Mark Delayed" },
{ PHASE_MARK_OTHER, "Mark Other" },
{ PHASE_FINALIZE_START, "Finalize Start Callback" },
{ PHASE_SWEEP, "Sweep" },
{ PHASE_SWEEP_COMPARTMENTS, "Sweep Compartments" },
{ PHASE_SWEEP_OBJECT, "Sweep Object" },
{ PHASE_SWEEP_STRING, "Sweep String" },
{ PHASE_SWEEP_SCRIPT, "Sweep Script" },
{ PHASE_SWEEP_SHAPE, "Sweep Shape" },
{ PHASE_DISCARD_CODE, "Discard Code" },
{ PHASE_DISCARD_ANALYSIS, "Discard Analysis" },
{ PHASE_DISCARD_TI, "Discard TI" },
{ PHASE_SWEEP_TYPES, "Sweep Types" },
{ PHASE_CLEAR_SCRIPT_ANALYSIS, "Clear Script Analysis" },
{ PHASE_FINALIZE_END, "Finalize End Callback" },
{ PHASE_DESTROY, "Deallocate" },
{ PHASE_GC_END, "End Callback" },
{ 0, NULL }
};
static void
formatPhases(StatisticsSerializer &ss, const char *name, int64_t *times)
FormatPhaseTimes(StatisticsSerializer &ss, const char *name, int64_t *times)
{
ss.beginObject(name);
ss.appendIfNonzeroMS("Begin Callback", t(times[PHASE_GC_BEGIN]));
ss.appendIfNonzeroMS("Wait Background Thread", t(times[PHASE_WAIT_BACKGROUND_THREAD]));
ss.appendIfNonzeroMS("Purge", t(times[PHASE_PURGE]));
ss.appendIfNonzeroMS("Mark", t(times[PHASE_MARK]));
ss.appendIfNonzeroMS("Mark Roots", t(times[PHASE_MARK_ROOTS]));
ss.appendIfNonzeroMS("Mark Delayed", t(times[PHASE_MARK_DELAYED]));
ss.appendIfNonzeroMS("Mark Other", t(times[PHASE_MARK_OTHER]));
ss.appendIfNonzeroMS("Finalize Start Callback", t(times[PHASE_FINALIZE_START]));
ss.appendIfNonzeroMS("Sweep", t(times[PHASE_SWEEP]));
ss.appendIfNonzeroMS("Sweep Compartments", t(times[PHASE_SWEEP_COMPARTMENTS]));
ss.appendIfNonzeroMS("Sweep Object", t(times[PHASE_SWEEP_OBJECT]));
ss.appendIfNonzeroMS("Sweep String", t(times[PHASE_SWEEP_STRING]));
ss.appendIfNonzeroMS("Sweep Script", t(times[PHASE_SWEEP_SCRIPT]));
ss.appendIfNonzeroMS("Sweep Shape", t(times[PHASE_SWEEP_SHAPE]));
ss.appendIfNonzeroMS("Discard Code", t(times[PHASE_DISCARD_CODE]));
ss.appendIfNonzeroMS("Discard Analysis", t(times[PHASE_DISCARD_ANALYSIS]));
ss.appendIfNonzeroMS("Discard TI", t(times[PHASE_DISCARD_TI]));
ss.appendIfNonzeroMS("Sweep Types", t(times[PHASE_SWEEP_TYPES]));
ss.appendIfNonzeroMS("Clear Script Analysis", t(times[PHASE_CLEAR_SCRIPT_ANALYSIS]));
ss.appendIfNonzeroMS("Finalize End Callback", t(times[PHASE_FINALIZE_END]));
ss.appendIfNonzeroMS("Deallocate", t(times[PHASE_DESTROY]));
ss.appendIfNonzeroMS("End Callback", t(times[PHASE_GC_END]));
for (unsigned i = 0; phases[i].name; i++)
ss.appendIfNonzeroMS(phases[i].name, t(times[phases[i].index]));
ss.endObject();
}
static void
FormatPhaseFaults(StatisticsSerializer &ss, const char *name, size_t *faults)
{
ss.beginObject(name);
for (unsigned i = 0; phases[i].name; i++)
ss.appendNumber(phases[i].name, "%u", "", unsigned(faults[phases[i].index]));
ss.endObject();
}
@@ -365,21 +387,25 @@ Statistics::formatData(StatisticsSerializer &ss, uint64_t timestamp)
ss.beginObject(NULL);
ss.extra(" ");
ss.appendNumber("Slice", "%d", "", i);
ss.appendDecimal("Time", "ms", t(slices[i].end - slices[0].start));
ss.extra(" (");
ss.appendDecimal("Pause", "", t(width));
ss.extra(" (");
ss.appendDecimal("When", "ms", t(slices[i].end - slices[0].start));
ss.appendString("Reason", ExplainReason(slices[i].reason));
if (slices[i].resetReason)
ss.appendString("Reset", slices[i].resetReason);
ss.extra("): ");
formatPhases(ss, "times", slices[i].phaseTimes);
FormatPhaseTimes(ss, "Times", slices[i].phaseTimes);
if (ss.isJSON())
FormatPhaseFaults(ss, "Page Faults", slices[i].phaseFaults);
ss.endLine();
ss.endObject();
}
ss.endArray();
}
ss.extra(" Totals: ");
formatPhases(ss, "totals", phaseTimes);
FormatPhaseTimes(ss, "Totals", phaseTimes);
if (ss.isJSON())
FormatPhaseFaults(ss, "Total Page Faults", phaseFaults);
ss.endObject();
return !ss.isOOM();
@@ -439,7 +465,7 @@ Statistics::~Statistics()
if (fp) {
if (fullFormat) {
StatisticsSerializer ss(StatisticsSerializer::AsText);
formatPhases(ss, "", phaseTotals);
FormatPhaseTimes(ss, "", phaseTotals);
char *msg = ss.finishCString();
if (msg) {
fprintf(fp, "TOTALS\n%s\n\n-------\n", msg);
@@ -481,8 +507,10 @@ Statistics::printStats()
void
Statistics::beginGC()
{
PodArrayZero(phaseStarts);
PodArrayZero(phaseStartTimes);
PodArrayZero(phaseStartFaults);
PodArrayZero(phaseTimes);
PodArrayZero(phaseFaults);
slices.clearAndFree();
nonincrementalReason = NULL;
@@ -570,7 +598,8 @@ Statistics::endSlice()
void
Statistics::beginPhase(Phase phase)
{
phaseStarts[phase] = PRMJ_Now();
phaseStartTimes[phase] = PRMJ_Now();
phaseStartFaults[phase] = gc::GetPageFaultCount();
if (phase == gcstats::PHASE_MARK)
Probes::GCStartMarkPhase();
@@ -581,11 +610,14 @@ Statistics::beginPhase(Phase phase)
void
Statistics::endPhase(Phase phase)
{
int64_t now = PRMJ_Now();
int64_t t = now - phaseStarts[phase];
int64_t t = PRMJ_Now() - phaseStartTimes[phase];
slices.back().phaseTimes[phase] += t;
phaseTimes[phase] += t;
size_t faults = gc::GetPageFaultCount() - phaseStartFaults[phase];
slices.back().phaseFaults[phase] += faults;
phaseFaults[phase] += faults;
if (phase == gcstats::PHASE_MARK)
Probes::GCEndMarkPhase();
else if (phase == gcstats::PHASE_SWEEP)