Bug 745034 - Add page fault counts to GC statistics (r=terrence,dmandelin)
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user