author | Jon Coppeard <jcoppeard@mozilla.com> |
Wed, 29 Oct 2014 16:52:05 +0000 | |
changeset 212990 | 3479b8c7cc8d4ce6d4af9853cc2c086beea28c43 |
parent 212989 | f05aa42d06e9a06855db5e1d70b93e23f2073386 |
child 212991 | 0259e2c45c3d7bb796e87b11f5eea261e11d09ea |
push id | 27738 |
push user | cbook@mozilla.com |
push date | Thu, 30 Oct 2014 13:46:07 +0000 |
treeherder | mozilla-central@1aa1b23d799e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | terrence |
bugs | 650161 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -238,16 +238,26 @@ class gcstats::StatisticsSerializer /* * If this fails, then you can either delete this assertion and allow all * larger-numbered reasons to pile up in the last telemetry bucket, or switch * to GC_REASON_3 and bump the max value. */ JS_STATIC_ASSERT(JS::gcreason::NUM_TELEMETRY_REASONS >= JS::gcreason::NUM_REASONS); const char * +js::gcstats::ExplainInvocationKind(JSGCInvocationKind gckind) +{ + MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK); + if (gckind == GC_NORMAL) + return "Normal"; + else + return "Shrinking"; +} + +const char * js::gcstats::ExplainReason(JS::gcreason::Reason reason) { switch (reason) { #define SWITCH_REASON(name) \ case JS::gcreason::name: \ return #name; GCREASONS(SWITCH_REASON) @@ -455,29 +465,31 @@ Statistics::formatDescription() int64_t sccTotal, sccLongest; sccDurations(&sccTotal, &sccLongest); double mmu20 = computeMMU(20 * PRMJ_USEC_PER_MSEC); double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC); const char *format = "=================================================================\n\ + Invocation Kind: %s\n\ Reason: %s\n\ Incremental: %s%s\n\ Zones Collected: %d of %d\n\ Compartments Collected: %d of %d\n\ MinorGCs since last GC: %d\n\ MMU 20ms:%.1f%%; 50ms:%.1f%%\n\ SCC Sweep Total (MaxPause): %.3fms (%.3fms)\n\ HeapSize: %.3f MiB\n\ Chunk Delta (magnitude): %+d (%d)\n\ "; char buffer[1024]; memset(buffer, 0, sizeof(buffer)); JS_snprintf(buffer, sizeof(buffer), format, + ExplainInvocationKind(gckind), ExplainReason(slices[0].reason), nonincrementalReason ? "no - " : "yes", nonincrementalReason ? nonincrementalReason : "", zoneStats.collectedZoneCount, zoneStats.zoneCount, zoneStats.collectedCompartmentCount, zoneStats.compartmentCount, counts[STAT_MINOR_GC], mmu20 * 100., mmu50 * 100., t(sccTotal), t(sccLongest), @@ -704,23 +716,24 @@ Statistics::printStats() t(total), t(phaseTimes[PHASE_MARK]), t(phaseTimes[PHASE_SWEEP])); } fflush(fp); } void -Statistics::beginGC() +Statistics::beginGC(JSGCInvocationKind kind) { PodArrayZero(phaseStartTimes); PodArrayZero(phaseTimes); slices.clearAndFree(); sccTimes.clearAndFree(); + gckind = kind; nonincrementalReason = nullptr; preBytes = runtime->gc.usage.gcBytes(); } void Statistics::endGC() { @@ -752,23 +765,24 @@ Statistics::endGC() (*cb)(JS_TELEMETRY_GC_MMU_50, mmu50 * 100); } if (fp) printStats(); } void -Statistics::beginSlice(const ZoneGCStats &zoneStats, JS::gcreason::Reason reason) +Statistics::beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind, + JS::gcreason::Reason reason) { this->zoneStats = zoneStats; bool first = runtime->gc.state() == gc::NO_INCREMENTAL; if (first) - beginGC(); + beginGC(gckind); SliceData data(reason, PRMJ_Now(), GetPageFaultCount()); if (!slices.append(data)) CrashAtUnhandlableOOM("Failed to allocate statistics slice."); if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) (*cb)(JS_TELEMETRY_GC_REASON, reason);
--- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -7,16 +7,17 @@ #ifndef gc_Statistics_h #define gc_Statistics_h #include "mozilla/DebugOnly.h" #include "mozilla/PodOperations.h" #include "mozilla/UniquePtr.h" #include "jsalloc.h" +#include "jsgc.h" #include "jspubtd.h" #include "js/GCAPI.h" #include "js/Vector.h" struct JSCompartment; namespace js { @@ -108,17 +109,18 @@ struct Statistics { explicit Statistics(JSRuntime *rt); ~Statistics(); void beginPhase(Phase phase); void endPhase(Phase phase); void endParallelPhase(Phase phase, const GCParallelTask *task); - void beginSlice(const ZoneGCStats &zoneStats, JS::gcreason::Reason reason); + void beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); void endSlice(); void reset(const char *reason) { slices.back().resetReason = reason; } void nonincremental(const char *reason) { nonincrementalReason = reason; } void count(Stat s) { MOZ_ASSERT(s < STAT_LIMIT); counts[s]++; @@ -147,16 +149,18 @@ struct Statistics /* * GCs can't really nest, but a second GC can be triggered from within the * JSGC_END callback. */ int gcDepth; ZoneGCStats zoneStats; + JSGCInvocationKind gckind; + const char *nonincrementalReason; struct SliceData { SliceData(JS::gcreason::Reason reason, int64_t start, size_t startFaults) : reason(reason), resetReason(nullptr), start(start), startFaults(startFaults) { mozilla::PodArrayZero(phaseTimes); } @@ -197,17 +201,17 @@ struct Statistics #endif mozilla::DebugOnly<size_t> phaseNestingDepth; /* Sweep times for SCCs of compartments. */ Vector<int64_t, 0, SystemAllocPolicy> sccTimes; JS::GCSliceCallback sliceCallback; - void beginGC(); + void beginGC(JSGCInvocationKind kind); void endGC(); void gcDuration(int64_t *total, int64_t *maxPause); void sccDurations(int64_t *total, int64_t *maxPause); void printStats(); bool formatData(StatisticsSerializer &ss, uint64_t timestamp); UniqueChars formatDescription(); @@ -215,22 +219,23 @@ struct Statistics UniqueChars formatTotals(); UniqueChars formatPhaseTimes(int64_t *phaseTimes); double computeMMU(int64_t resolution); }; struct AutoGCSlice { - AutoGCSlice(Statistics &stats, const ZoneGCStats &zoneStats, JS::gcreason::Reason reason + AutoGCSlice(Statistics &stats, const ZoneGCStats &zoneStats, JSGCInvocationKind gckind, + JS::gcreason::Reason reason MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : stats(stats) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - stats.beginSlice(zoneStats, reason); + stats.beginSlice(zoneStats, gckind, reason); } ~AutoGCSlice() { stats.endSlice(); } Statistics &stats; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; struct AutoPhase @@ -291,14 +296,15 @@ struct AutoSCC } Statistics &stats; unsigned scc; int64_t start; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; +const char *ExplainInvocationKind(JSGCInvocationKind gckind); const char *ExplainReason(JS::gcreason::Reason reason); } /* namespace gcstats */ } /* namespace js */ #endif /* gc_Statistics_h */
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -5979,17 +5979,17 @@ GCRuntime::collect(bool incremental, int return; #endif MOZ_ASSERT_IF(!incremental || budget != SliceBudget::Unlimited, JSGC_INCREMENTAL); AutoStopVerifyingBarriers av(rt, reason == JS::gcreason::SHUTDOWN_CC || reason == JS::gcreason::DESTROY_RUNTIME); - gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), reason); + gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), gckind, reason); cleanUpEverything = ShouldCleanUpEverything(reason, gckind); bool repeat = false; do { /* * Let the API user decide to defer a GC if it wants to (unless this * is the last context). Invoke the callback regardless.