author | Terrence Cole <terrence@mozilla.com> |
Thu, 04 Jun 2015 11:49:31 -0700 | |
changeset 248183 | 53d75ce7f7fd831fb8c889e579a45b140cc04cbd |
parent 248182 | 46871501aaa3c1ce2347a80d0be394a0792caf12 |
child 248184 | a3e12ac67218200b44f0b9fe0ef484583a40d0c0 |
push id | 28893 |
push user | kwierso@gmail.com |
push date | Fri, 12 Jun 2015 00:02:58 +0000 |
treeherder | autoland@8cf9d3e497f9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1171612 |
milestone | 41.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
|
js/src/gc/Statistics.cpp | file | annotate | diff | comparison | revisions | |
js/src/gc/Statistics.h | file | annotate | diff | comparison | revisions |
--- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -2,16 +2,17 @@ * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gc/Statistics.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/IntegerRange.h" #include "mozilla/PodOperations.h" #include "mozilla/UniquePtr.h" #include <ctype.h> #include <stdarg.h> #include <stdio.h> #include "jsprf.h" @@ -22,16 +23,17 @@ #include "vm/Debugger.h" #include "vm/HelperThreads.h" #include "vm/Runtime.h" using namespace js; using namespace js::gc; using namespace js::gcstats; +using mozilla::MakeRange; using mozilla::PodArrayZero; using mozilla::PodZero; /* Except for the first and last, slices of less than 10ms are not reported. */ static const int64_t SLICE_MIN_REPORT_TIME = 10 * PRMJ_USEC_PER_MSEC; /* * If this fails, then you can either delete this assertion and allow all @@ -180,25 +182,25 @@ static const PhaseInfo phases[] = { { PHASE_LIMIT, nullptr, PHASE_NO_PARENT } }; static ExtraPhaseInfo phaseExtra[PHASE_LIMIT] = { { 0, 0 } }; // Mapping from all nodes with a multi-parented child to a Vector of all // multi-parented children and their descendants. (Single-parented children will // not show up in this list.) -static mozilla::Vector<Phase> dagDescendants[Statistics::MAX_MULTIPARENT_PHASES + 1]; +static mozilla::Vector<Phase> dagDescendants[Statistics::NumTimingArrays]; struct AllPhaseIterator { int current; int baseLevel; size_t activeSlot; mozilla::Vector<Phase>::Range descendants; - explicit AllPhaseIterator(Statistics::PhaseTimeTable table) + explicit AllPhaseIterator(const Statistics::PhaseTimeTable table) : current(0) , baseLevel(0) , activeSlot(PHASE_DAG_NONE) , descendants(dagDescendants[PHASE_DAG_NONE].all()) /* empty range */ { } void get(Phase* phase, size_t* dagSlot, size_t* level = nullptr) { @@ -288,17 +290,17 @@ Join(const FragmentVector& fragments, co cursor += separatorLength; } } return UniqueChars(joined); } static int64_t -SumChildTimes(size_t phaseSlot, Phase phase, Statistics::PhaseTimeTable phaseTimes) +SumChildTimes(size_t phaseSlot, Phase phase, const Statistics::PhaseTimeTable phaseTimes) { // Sum the contributions from single-parented children. int64_t total = 0; for (unsigned i = 0; i < PHASE_LIMIT; i++) { if (phases[i].parent == phase) total += phaseTimes[phaseSlot][i]; } @@ -393,17 +395,17 @@ Statistics::formatCompactSummaryMessage( if (!fragments.append(make_string_copy(buffer))) return UniqueChars(nullptr); } return Join(fragments); } UniqueChars -Statistics::formatCompactSlicePhaseTimes(PhaseTimeTable phaseTimes) const +Statistics::formatCompactSlicePhaseTimes(const PhaseTimeTable phaseTimes) const { static const int64_t MaxUnaccountedTimeUS = 100; FragmentVector fragments; char buffer[128]; for (AllPhaseIterator iter(phaseTimes); !iter.done(); iter.advance()) { Phase phase; size_t dagSlot; @@ -519,17 +521,17 @@ Statistics::formatDetailedSliceDescripti ExplainReason(slice.reason), slice.resetReason ? "yes - " : "no", slice.resetReason ? slice.resetReason : "", uint64_t(slice.endFaults - slice.startFaults), t(slice.duration()), budgetDescription, t(slice.start - slices[0].start)); return make_string_copy(buffer); } UniqueChars -Statistics::formatDetailedPhaseTimes(PhaseTimeTable phaseTimes) +Statistics::formatDetailedPhaseTimes(const PhaseTimeTable phaseTimes) { static const char* LevelToIndent[] = { "", " ", " ", " " }; static const int64_t MaxUnaccountedChildTimeUS = 50; FragmentVector fragments; char buffer[128]; for (AllPhaseIterator iter(phaseTimes); !iter.done(); iter.advance()) { Phase phase; @@ -706,17 +708,17 @@ FilterJsonKey(const char*const buffer) else if (isupper(*c)) *c = tolower(*c); ++c; } return UniqueChars(mut); } UniqueChars -Statistics::formatJsonPhaseTimes(PhaseTimeTable phaseTimes) +Statistics::formatJsonPhaseTimes(const PhaseTimeTable phaseTimes) { FragmentVector fragments; char buffer[128]; for (AllPhaseIterator iter(phaseTimes); !iter.done(); iter.advance()) { Phase phase; size_t dagSlot; iter.get(&phase, &dagSlot); @@ -744,17 +746,17 @@ Statistics::Statistics(JSRuntime* rt) activeDagSlot(PHASE_DAG_NONE), suspendedPhaseNestingDepth(0), sliceCallback(nullptr), aborted(false) { PodArrayZero(phaseTotals); PodArrayZero(counts); PodArrayZero(phaseStartTimes); - for (size_t d = 0; d < MAX_MULTIPARENT_PHASES + 1; d++) + for (auto d : MakeRange(NumTimingArrays)) PodArrayZero(phaseTimes[d]); static bool initialized = false; if (!initialized) { initialized = true; for (size_t i = 0; i < PHASE_LIMIT; i++) MOZ_ASSERT(phases[i].index == i); @@ -773,17 +775,17 @@ Statistics::Statistics(JSRuntime* rt) Phase child = dagChildEdges[i].child; MOZ_ASSERT(phases[child].parent == PHASE_MULTI_PARENTS); int j = child; do { dagDescendants[phaseExtra[parent].dagSlot].append(Phase(j)); j++; } while (j != PHASE_LIMIT && phases[j].parent != PHASE_MULTI_PARENTS); } - MOZ_ASSERT(dagSlot <= MAX_MULTIPARENT_PHASES); + MOZ_ASSERT(dagSlot <= MaxMultiparentPhases - 1); // Fill in the depth of each node in the tree. Multi-parented nodes // have depth 0. mozilla::Vector<Phase> stack; stack.append(PHASE_LIMIT); // Dummy entry to avoid special-casing the first node for (int i = 0; i < PHASE_LIMIT; i++) { if (phases[i].parent == PHASE_NO_PARENT || phases[i].parent == PHASE_MULTI_PARENTS) @@ -841,17 +843,17 @@ Statistics::getMaxGCPauseSinceClear() { return maxPauseInInterval; } static int64_t SumPhase(Phase phase, Statistics::PhaseTimeTable times) { int64_t sum = 0; - for (size_t i = 0; i < Statistics::MAX_MULTIPARENT_PHASES + 1; i++) + for (auto i : MakeRange(Statistics::NumTimingArrays)) sum += times[i][phase]; return sum; } void Statistics::printStats() { if (aborted) { @@ -873,17 +875,17 @@ Statistics::beginGC(JSGCInvocationKind k nonincrementalReason_ = nullptr; preBytes = runtime->gc.usage.gcBytes(); } void Statistics::endGC() { - for (size_t j = 0; j < MAX_MULTIPARENT_PHASES + 1; j++) + for (auto j : MakeRange(NumTimingArrays)) for (int i = 0; i < PHASE_LIMIT; i++) phaseTotals[j][i] += phaseTimes[j][i]; int64_t total, longest; gcDuration(&total, &longest); int64_t sccTotal, sccLongest; sccDurations(&sccTotal, &sccLongest); @@ -908,17 +910,17 @@ Statistics::endGC() } if (fp) printStats(); // Clear the timers at the end of a GC because we accumulate time in // between GCs for some (which come before PHASE_GC_BEGIN in the list.) PodZero(&phaseStartTimes[PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN); - for (size_t d = PHASE_DAG_NONE; d < MAX_MULTIPARENT_PHASES + 1; d++) + for (size_t d = PHASE_DAG_NONE; d < NumTimingArrays; d++) PodZero(&phaseTimes[d][PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN); aborted = false; } void Statistics::beginSlice(const ZoneGCStats& zoneStats, JSGCInvocationKind gckind, SliceBudget budget, JS::gcreason::Reason reason)
--- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -3,16 +3,17 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef gc_Statistics_h #define gc_Statistics_h #include "mozilla/DebugOnly.h" +#include "mozilla/IntegerRange.h" #include "mozilla/PodOperations.h" #include "mozilla/UniquePtr.h" #include "jsalloc.h" #include "jsgc.h" #include "jspubtd.h" #include "js/GCAPI.h" @@ -146,17 +147,21 @@ struct Statistics * Note that this wastes quite a bit of space, since we have a whole * separate array of timing data containing all the phases. We could be * more clever and keep an array of pointers biased by the offset of the * multi-parented phase, and thereby preserve the simple * timings[slot][PHASE_*] indexing. But the complexity doesn't seem worth * the few hundred bytes of savings. If we want to extend things to full * DAGs, this decision should be reconsidered. */ - static const size_t MAX_MULTIPARENT_PHASES = 6; + static const size_t MaxMultiparentPhases = 6; + static const size_t NumTimingArrays = MaxMultiparentPhases + 1; + + /* Create a convenient type for referring to tables of phase times. */ + using PhaseTimeTable = int64_t[NumTimingArrays][PHASE_LIMIT]; explicit Statistics(JSRuntime* rt); ~Statistics(); void beginPhase(Phase phase); void endPhase(Phase phase); void endParallelPhase(Phase phase, const GCParallelTask* task); @@ -206,39 +211,36 @@ struct Statistics static const size_t MAX_NESTING = 20; struct SliceData { SliceData(SliceBudget budget, JS::gcreason::Reason reason, int64_t start, size_t startFaults) : budget(budget), reason(reason), resetReason(nullptr), start(start), startFaults(startFaults) { - for (size_t i = 0; i < MAX_MULTIPARENT_PHASES + 1; i++) + for (auto i : mozilla::MakeRange(NumTimingArrays)) mozilla::PodArrayZero(phaseTimes[i]); } SliceBudget budget; JS::gcreason::Reason reason; const char* resetReason; int64_t start, end; size_t startFaults, endFaults; - int64_t phaseTimes[MAX_MULTIPARENT_PHASES + 1][PHASE_LIMIT]; + PhaseTimeTable phaseTimes; int64_t duration() const { return end - start; } }; typedef Vector<SliceData, 8, SystemAllocPolicy> SliceDataVector; typedef SliceDataVector::ConstRange SliceRange; SliceRange sliceRange() const { return slices.all(); } size_t slicesLength() const { return slices.length(); } - /* Create a convenient typedef for referring tables of phase times. */ - typedef int64_t const (*PhaseTimeTable)[PHASE_LIMIT]; - private: JSRuntime* runtime; int64_t startupTime; /* File pointer used for MOZ_GCTIMER output. */ FILE* fp; @@ -259,20 +261,20 @@ struct Statistics /* Most recent time when the given phase started. */ int64_t phaseStartTimes[PHASE_LIMIT]; /* Bookkeeping for GC timings when timingMutator is true */ int64_t timedGCStart; int64_t timedGCTime; /* Total time in a given phase for this GC. */ - int64_t phaseTimes[MAX_MULTIPARENT_PHASES + 1][PHASE_LIMIT]; + PhaseTimeTable phaseTimes; /* Total time in a given phase over all GCs. */ - int64_t phaseTotals[MAX_MULTIPARENT_PHASES + 1][PHASE_LIMIT]; + PhaseTimeTable phaseTotals; /* Number of events of this type for this GC. */ unsigned int counts[STAT_LIMIT]; /* Allocated space before the GC started. */ size_t preBytes; /* Records the maximum GC pause in an API-controlled interval (in us). */ @@ -307,26 +309,26 @@ struct Statistics void endGC(); void recordPhaseEnd(Phase phase); void gcDuration(int64_t* total, int64_t* maxPause) const; void sccDurations(int64_t* total, int64_t* maxPause); void printStats(); - UniqueChars formatCompactSlicePhaseTimes(PhaseTimeTable phaseTimes) const; + UniqueChars formatCompactSlicePhaseTimes(const PhaseTimeTable phaseTimes) const; UniqueChars formatDetailedDescription(); UniqueChars formatDetailedSliceDescription(unsigned i, const SliceData& slice); - UniqueChars formatDetailedPhaseTimes(PhaseTimeTable phaseTimes); + UniqueChars formatDetailedPhaseTimes(const PhaseTimeTable phaseTimes); UniqueChars formatDetailedTotals(); UniqueChars formatJsonDescription(uint64_t timestamp); UniqueChars formatJsonSliceDescription(unsigned i, const SliceData& slice); - UniqueChars formatJsonPhaseTimes(PhaseTimeTable phaseTimes); + UniqueChars formatJsonPhaseTimes(const PhaseTimeTable phaseTimes); double computeMMU(int64_t resolution) const; }; struct AutoGCSlice { AutoGCSlice(Statistics& stats, const ZoneGCStats& zoneStats, JSGCInvocationKind gckind, SliceBudget budget, JS::gcreason::Reason reason