зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1367900 - Record the values and thresholds for GC triggers, r=jonco
--HG-- extra : rebase_source : 324a41ddd6a0f577c5f44611e5fcdd092ef05d2d extra : amend_source : 34470a4ff7d1591811bd6d8f757c71747fd86f99
This commit is contained in:
Родитель
a6d47c0012
Коммит
d08266fbd1
|
@ -688,7 +688,8 @@ class GCRuntime
|
|||
MOZ_MUST_USE bool triggerGC(JS::gcreason::Reason reason);
|
||||
void maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock);
|
||||
// The return value indicates if we were able to do the GC.
|
||||
bool triggerZoneGC(Zone* zone, JS::gcreason::Reason reason);
|
||||
bool triggerZoneGC(Zone* zone, JS::gcreason::Reason reason,
|
||||
size_t usedBytes, size_t thresholdBytes);
|
||||
void maybeGC(Zone* zone);
|
||||
// The return value indicates whether a major GC was performed.
|
||||
bool gcIfRequested();
|
||||
|
@ -796,7 +797,10 @@ class GCRuntime
|
|||
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||
|
||||
bool triggerGCForTooMuchMalloc() { return triggerGC(JS::gcreason::TOO_MUCH_MALLOC); }
|
||||
bool triggerGCForTooMuchMalloc() {
|
||||
stats().recordTrigger(mallocCounter.bytes(), mallocCounter.maxBytes());
|
||||
return triggerGC(JS::gcreason::TOO_MUCH_MALLOC);
|
||||
}
|
||||
int32_t getMallocBytes() const { return mallocCounter.bytes(); }
|
||||
size_t maxMallocBytesAllocated() const { return mallocCounter.maxBytes(); }
|
||||
bool isTooMuchMalloc() const { return mallocCounter.isTooMuchMalloc(); }
|
||||
|
|
|
@ -617,6 +617,11 @@ Statistics::formatJsonSliceDescription(unsigned i, const SliceData& slice, JSONP
|
|||
json.property("initial_state", gc::StateName(slice.initialState));
|
||||
json.property("final_state", gc::StateName(slice.finalState));
|
||||
json.property("budget", budgetDescription);
|
||||
json.property("major_gc_number", startingMajorGCNumber);
|
||||
if (thresholdTriggered) {
|
||||
json.floatProperty("trigger_amount", triggerAmount, 0);
|
||||
json.floatProperty("trigger_threshold", triggerThreshold, 0);
|
||||
}
|
||||
json.property("page_faults", int64_t(slice.endFaults - slice.startFaults));
|
||||
json.property("start_timestamp", slice.start - originTime, JSONPrinter::SECONDS);
|
||||
json.property("end_timestamp", slice.end - originTime, JSONPrinter::SECONDS);
|
||||
|
@ -637,6 +642,9 @@ Statistics::Statistics(JSRuntime* rt)
|
|||
fp(nullptr),
|
||||
nonincrementalReason_(gc::AbortReason::None),
|
||||
preBytes(0),
|
||||
thresholdTriggered(false),
|
||||
triggerAmount(0.0),
|
||||
triggerThreshold(0.0),
|
||||
maxPauseInInterval(0),
|
||||
sliceCallback(nullptr),
|
||||
nurseryCollectionCallback(nullptr),
|
||||
|
@ -891,6 +899,7 @@ Statistics::endGC()
|
|||
|
||||
// Clear the OOM flag.
|
||||
aborted = false;
|
||||
thresholdTriggered = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -187,6 +187,12 @@ struct Statistics
|
|||
return uint32_t(counts[s]);
|
||||
}
|
||||
|
||||
void recordTrigger(double amount, double threshold) {
|
||||
triggerAmount = amount;
|
||||
triggerThreshold = threshold;
|
||||
thresholdTriggered = true;
|
||||
}
|
||||
|
||||
void beginNurseryCollection(JS::gcreason::Reason reason);
|
||||
void endNurseryCollection(JS::gcreason::Reason reason);
|
||||
|
||||
|
@ -296,6 +302,12 @@ struct Statistics
|
|||
/* Allocated space before the GC started. */
|
||||
size_t preBytes;
|
||||
|
||||
/* If the GC was triggered by exceeding some threshold, record the
|
||||
* threshold and the value that exceeded it. */
|
||||
bool thresholdTriggered;
|
||||
double triggerAmount;
|
||||
double triggerThreshold;
|
||||
|
||||
/* GC numbers as of the beginning of the collection. */
|
||||
uint64_t startingMinorGCNumber;
|
||||
uint64_t startingMajorGCNumber;
|
||||
|
|
|
@ -407,10 +407,11 @@ struct Zone : public JS::shadow::Zone,
|
|||
bool triggerGCForTooMuchMalloc() {
|
||||
JSRuntime* rt = runtimeFromAnyThread();
|
||||
|
||||
if (CurrentThreadCanAccessRuntime(rt))
|
||||
return rt->gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC);
|
||||
else
|
||||
return false;
|
||||
if (CurrentThreadCanAccessRuntime(rt)) {
|
||||
return rt->gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC,
|
||||
gcMallocCounter.bytes(), gcMallocCounter.maxBytes());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void resetGCMallocBytes() { gcMallocCounter.reset(); }
|
||||
|
|
|
@ -3030,7 +3030,7 @@ GCRuntime::maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock)
|
|||
* The threshold has been surpassed, immediately trigger a GC,
|
||||
* which will be done non-incrementally.
|
||||
*/
|
||||
triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER);
|
||||
triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER, usedBytes, thresholdBytes);
|
||||
} else {
|
||||
bool wouldInterruptCollection;
|
||||
size_t igcThresholdBytes;
|
||||
|
@ -3056,7 +3056,7 @@ GCRuntime::maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock)
|
|||
// to try to avoid performing non-incremental GCs on zones
|
||||
// which allocate a lot of data, even when incremental slices
|
||||
// can't be triggered via scheduling in the event loop.
|
||||
triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER);
|
||||
triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER, usedBytes, igcThresholdBytes);
|
||||
|
||||
// Delay the next slice until a certain amount of allocation
|
||||
// has been performed.
|
||||
|
@ -3067,7 +3067,7 @@ GCRuntime::maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock)
|
|||
}
|
||||
|
||||
bool
|
||||
GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason)
|
||||
GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason, size_t used, size_t threshold)
|
||||
{
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
|
||||
|
@ -3090,10 +3090,12 @@ GCRuntime::triggerZoneGC(Zone* zone, JS::gcreason::Reason reason)
|
|||
fullGCForAtomsRequested_ = true;
|
||||
return false;
|
||||
}
|
||||
stats().recordTrigger(used, threshold);
|
||||
MOZ_RELEASE_ASSERT(triggerGC(reason));
|
||||
return true;
|
||||
}
|
||||
|
||||
stats().recordTrigger(used, threshold);
|
||||
PrepareZoneForGC(zone);
|
||||
requestMajorGC(reason);
|
||||
return true;
|
||||
|
@ -3115,11 +3117,12 @@ GCRuntime::maybeGC(Zone* zone)
|
|||
if (gcIfRequested())
|
||||
return;
|
||||
|
||||
if (zone->usage.gcBytes() > 1024 * 1024 &&
|
||||
zone->usage.gcBytes() >= zone->threshold.allocTrigger(schedulingState.inHighFrequencyGCMode()) &&
|
||||
!isIncrementalGCInProgress() &&
|
||||
!isBackgroundSweeping())
|
||||
double threshold = zone->threshold.allocTrigger(schedulingState.inHighFrequencyGCMode());
|
||||
double usedBytes = zone->usage.gcBytes();
|
||||
if (usedBytes > 1024 * 1024 && usedBytes >= threshold &&
|
||||
!isIncrementalGCInProgress() && !isBackgroundSweeping())
|
||||
{
|
||||
stats().recordTrigger(usedBytes, threshold);
|
||||
PrepareZoneForGC(zone);
|
||||
startGC(GC_NORMAL, JS::gcreason::EAGER_ALLOC_TRIGGER);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче