зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1570905 - Rework the GC triggers to make the incremental trigger the default and the non-incremental trigger some factor of this r=sfink?
Differential Revision: https://phabricator.services.mozilla.com/D41606 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
dea1e66fa8
Коммит
992d6b6ce5
|
@ -2572,12 +2572,12 @@ void nsJSContext::EnsureStatics() {
|
|||
(void*)JSGC_ALLOCATION_THRESHOLD);
|
||||
Preferences::RegisterCallbackAndCall(
|
||||
SetMemoryPrefChangedCallbackInt,
|
||||
"javascript.options.mem.gc_allocation_threshold_factor",
|
||||
(void*)JSGC_ALLOCATION_THRESHOLD_FACTOR);
|
||||
"javascript.options.mem.gc_non_incremental_factor",
|
||||
(void*)JSGC_NON_INCREMENTAL_FACTOR);
|
||||
Preferences::RegisterCallbackAndCall(
|
||||
SetMemoryPrefChangedCallbackInt,
|
||||
"javascript.options.mem.gc_allocation_threshold_factor_avoid_interrupt",
|
||||
(void*)JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT);
|
||||
"javascript.options.mem.gc_avoid_interrupt_factor",
|
||||
(void*)JSGC_AVOID_INTERRUPT_FACTOR);
|
||||
|
||||
Preferences::RegisterCallbackAndCall(SetIncrementalCCPrefChangedCallback,
|
||||
"dom.cycle_collector.incremental");
|
||||
|
|
|
@ -130,7 +130,7 @@ typedef enum JSGCParamKey {
|
|||
* The "do we collect?" decision depends on various parameters and can be
|
||||
* summarised as:
|
||||
*
|
||||
* ZoneSize * 1/UsageFactor > Max(ThresholdBase, LastSize) * GrowthFactor
|
||||
* ZoneSize > Max(ThresholdBase, LastSize) * GrowthFactor * ThresholdFactor
|
||||
*
|
||||
* Where
|
||||
* ZoneSize: Current size of this zone.
|
||||
|
@ -139,9 +139,10 @@ typedef enum JSGCParamKey {
|
|||
* GrowthFactor: A number above 1, calculated based on some of the
|
||||
* following parameters.
|
||||
* See computeZoneHeapGrowthFactorForHeapSize() in GC.cpp
|
||||
* UsageFactor: JSGC_ALLOCATION_THRESHOLD_FACTOR or
|
||||
* JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT or 1.0 for
|
||||
* non-incremental collections.
|
||||
* ThresholdFactor: 1.0 for incremental collections or
|
||||
* JSGC_NON_INCREMENTAL_FACTOR or
|
||||
* JSGC_AVOID_INTERRUPT_FACTOR for non-incremental
|
||||
* collections.
|
||||
*
|
||||
* The RHS of the equation above is calculated and sets
|
||||
* zone->threshold.gcTriggerBytes(). When usage.gcBytes() surpasses
|
||||
|
@ -251,26 +252,26 @@ typedef enum JSGCParamKey {
|
|||
JSGC_COMPACTING_ENABLED = 23,
|
||||
|
||||
/**
|
||||
* Percentage for triggering a GC based on zone->threshold.gcTriggerBytes().
|
||||
* Percentage for how far over a trigger threshold we go before triggering a
|
||||
* non-incremental GC.
|
||||
*
|
||||
* When the heap reaches this percentage of the allocation threshold an
|
||||
* incremental collection is started.
|
||||
* We trigger an incremental GC when a trigger threshold is reached but the
|
||||
* collection may not be fast enough to keep up with the mutator. At some
|
||||
* point we finish the collection non-incrementally.
|
||||
*
|
||||
* Default: ZoneAllocThresholdFactorDefault
|
||||
* Default: NonIncrementalFactor
|
||||
* Pref: None
|
||||
*/
|
||||
JSGC_ALLOCATION_THRESHOLD_FACTOR = 25,
|
||||
JSGC_NON_INCREMENTAL_FACTOR = 25,
|
||||
|
||||
/**
|
||||
* Percentage for triggering a GC based on zone->threshold.gcTriggerBytes().
|
||||
* Percentage for how far over a trigger threshold we go before triggering an
|
||||
* incremental collection that would reset an in-progress collection.
|
||||
*
|
||||
* Used instead of the above percentage if if another GC (in different zones)
|
||||
* is already running.
|
||||
*
|
||||
* Default: ZoneAllocThresholdFactorAvoidInterruptDefault
|
||||
* Default: AvoidInterruptFactor
|
||||
* Pref: None
|
||||
*/
|
||||
JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT = 26,
|
||||
JSGC_AVOID_INTERRUPT_FACTOR = 26,
|
||||
|
||||
/**
|
||||
* Attempt to run a minor GC in the idle time if the free space falls
|
||||
|
|
|
@ -513,9 +513,8 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
|
|||
_("dynamicHeapGrowth", JSGC_DYNAMIC_HEAP_GROWTH, true) \
|
||||
_("dynamicMarkSlice", JSGC_DYNAMIC_MARK_SLICE, true) \
|
||||
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
|
||||
_("allocationThresholdFactor", JSGC_ALLOCATION_THRESHOLD_FACTOR, true) \
|
||||
_("allocationThresholdFactorAvoidInterrupt", \
|
||||
JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT, true) \
|
||||
_("nonIncrementalFactor", JSGC_NON_INCREMENTAL_FACTOR, true) \
|
||||
_("avoidInterruptFactor", JSGC_AVOID_INTERRUPT_FACTOR, true) \
|
||||
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
|
||||
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
|
||||
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
|
||||
|
|
171
js/src/gc/GC.cpp
171
js/src/gc/GC.cpp
|
@ -283,7 +283,7 @@ namespace gc {
|
|||
namespace TuningDefaults {
|
||||
|
||||
/* JSGC_ALLOCATION_THRESHOLD */
|
||||
static const size_t GCZoneAllocThresholdBase = 30 * 1024 * 1024;
|
||||
static const size_t GCZoneAllocThresholdBase = 27 * 1024 * 1024;
|
||||
|
||||
/*
|
||||
* JSGC_MIN_NURSERY_BYTES
|
||||
|
@ -294,11 +294,11 @@ static const size_t GCZoneAllocThresholdBase = 30 * 1024 * 1024;
|
|||
*/
|
||||
static const size_t GCMinNurseryBytes = 256 * 1024;
|
||||
|
||||
/* JSGC_ALLOCATION_THRESHOLD_FACTOR */
|
||||
static const float AllocThresholdFactor = 0.9f;
|
||||
/* JSGC_NON_INCREMENTAL_FACTOR */
|
||||
static const float NonIncrementalFactor = 1.12f;
|
||||
|
||||
/* JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT */
|
||||
static const float AllocThresholdFactorAvoidInterrupt = 0.9f;
|
||||
/* JSGC_AVOID_INTERRUPT_FACTOR */
|
||||
static const float AvoidInterruptFactor = 1.0f;
|
||||
|
||||
/* JSGC_ZONE_ALLOC_DELAY_KB */
|
||||
static const size_t ZoneAllocDelayBytes = 1024 * 1024;
|
||||
|
@ -359,7 +359,7 @@ static const float PretenureGroupThreshold = 3000;
|
|||
static const auto MinLastDitchGCPeriod = 60; // in seconds
|
||||
|
||||
/* JSGC_MALLOC_THRESHOLD_BASE */
|
||||
static const size_t MallocThresholdBase = 42 * 1024 * 1024;
|
||||
static const size_t MallocThresholdBase = 38 * 1024 * 1024;
|
||||
|
||||
/* JSGC_MALLOC_GROWTH_FACTOR */
|
||||
static const float MallocGrowthFactor = 1.5f;
|
||||
|
@ -368,14 +368,6 @@ static const float MallocGrowthFactor = 1.5f;
|
|||
} // namespace gc
|
||||
} // namespace js
|
||||
|
||||
/*
|
||||
* We start to incremental collection for a zone when a proportion of its
|
||||
* threshold is reached. This is configured by the
|
||||
* JSGC_ALLOCATION_THRESHOLD_FACTOR and
|
||||
* JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT parameters.
|
||||
*/
|
||||
static constexpr float MinAllocationThresholdFactor = 0.9f;
|
||||
|
||||
/*
|
||||
* We may start to collect a zone before its trigger threshold is reached if
|
||||
* GCRuntime::maybeGC() is called for that zone or we start collecting other
|
||||
|
@ -385,13 +377,12 @@ static constexpr float HighFrequencyEagerAllocTriggerFactor = 0.85f;
|
|||
static constexpr float LowFrequencyEagerAllocTriggerFactor = 0.9f;
|
||||
|
||||
/*
|
||||
* Don't allow heap growth factors to be set so low that collections could
|
||||
* Don't allow heap growth factors to be set so low that eager collections could
|
||||
* reduce the trigger threshold.
|
||||
*/
|
||||
static constexpr float MinHeapGrowthFactor =
|
||||
1.0f /
|
||||
Min(HighFrequencyEagerAllocTriggerFactor,
|
||||
Min(LowFrequencyEagerAllocTriggerFactor, MinAllocationThresholdFactor));
|
||||
1.0f / Min(HighFrequencyEagerAllocTriggerFactor,
|
||||
LowFrequencyEagerAllocTriggerFactor);
|
||||
|
||||
/* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
|
||||
static constexpr int IGC_MARK_SLICE_MULTIPLIER = 2;
|
||||
|
@ -1535,20 +1526,20 @@ bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value,
|
|||
case JSGC_ALLOCATION_THRESHOLD:
|
||||
gcZoneAllocThresholdBase_ = value * 1024 * 1024;
|
||||
break;
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR: {
|
||||
case JSGC_NON_INCREMENTAL_FACTOR: {
|
||||
float newFactor = value / 100.0f;
|
||||
if (newFactor < MinAllocationThresholdFactor || newFactor > 1.0f) {
|
||||
if (newFactor < 1.0f) {
|
||||
return false;
|
||||
}
|
||||
allocThresholdFactor_ = newFactor;
|
||||
nonIncrementalFactor_ = newFactor;
|
||||
break;
|
||||
}
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT: {
|
||||
case JSGC_AVOID_INTERRUPT_FACTOR: {
|
||||
float newFactor = value / 100.0f;
|
||||
if (newFactor < MinAllocationThresholdFactor || newFactor > 1.0f) {
|
||||
if (newFactor < 1.0f) {
|
||||
return false;
|
||||
}
|
||||
allocThresholdFactorAvoidInterrupt_ = newFactor;
|
||||
avoidInterruptFactor_ = newFactor;
|
||||
break;
|
||||
}
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
|
@ -1667,9 +1658,8 @@ GCSchedulingTunables::GCSchedulingTunables()
|
|||
gcMinNurseryBytes_(TuningDefaults::GCMinNurseryBytes),
|
||||
gcMaxNurseryBytes_(0),
|
||||
gcZoneAllocThresholdBase_(TuningDefaults::GCZoneAllocThresholdBase),
|
||||
allocThresholdFactor_(TuningDefaults::AllocThresholdFactor),
|
||||
allocThresholdFactorAvoidInterrupt_(
|
||||
TuningDefaults::AllocThresholdFactorAvoidInterrupt),
|
||||
nonIncrementalFactor_(TuningDefaults::NonIncrementalFactor),
|
||||
avoidInterruptFactor_(TuningDefaults::AvoidInterruptFactor),
|
||||
zoneAllocDelayBytes_(TuningDefaults::ZoneAllocDelayBytes),
|
||||
dynamicHeapGrowthEnabled_(TuningDefaults::DynamicHeapGrowthEnabled),
|
||||
highFrequencyThreshold_(
|
||||
|
@ -1757,12 +1747,11 @@ void GCSchedulingTunables::resetParameter(JSGCParamKey key,
|
|||
case JSGC_ALLOCATION_THRESHOLD:
|
||||
gcZoneAllocThresholdBase_ = TuningDefaults::GCZoneAllocThresholdBase;
|
||||
break;
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR:
|
||||
allocThresholdFactor_ = TuningDefaults::AllocThresholdFactor;
|
||||
case JSGC_NON_INCREMENTAL_FACTOR:
|
||||
nonIncrementalFactor_ = TuningDefaults::NonIncrementalFactor;
|
||||
break;
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT:
|
||||
allocThresholdFactorAvoidInterrupt_ =
|
||||
TuningDefaults::AllocThresholdFactorAvoidInterrupt;
|
||||
case JSGC_AVOID_INTERRUPT_FACTOR:
|
||||
avoidInterruptFactor_ = TuningDefaults::AvoidInterruptFactor;
|
||||
break;
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
setMinEmptyChunkCount(TuningDefaults::MinEmptyChunkCount);
|
||||
|
@ -1850,10 +1839,10 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
|
|||
return tunables.isDynamicMarkSliceEnabled();
|
||||
case JSGC_ALLOCATION_THRESHOLD:
|
||||
return tunables.gcZoneAllocThresholdBase() / 1024 / 1024;
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR:
|
||||
return uint32_t(tunables.allocThresholdFactor() * 100);
|
||||
case JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT:
|
||||
return uint32_t(tunables.allocThresholdFactorAvoidInterrupt() * 100);
|
||||
case JSGC_NON_INCREMENTAL_FACTOR:
|
||||
return uint32_t(tunables.nonIncrementalFactor() * 100);
|
||||
case JSGC_AVOID_INTERRUPT_FACTOR:
|
||||
return uint32_t(tunables.avoidInterruptFactor() * 100);
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
return tunables.minEmptyChunkCount(lock);
|
||||
case JSGC_MAX_EMPTY_CHUNK_COUNT:
|
||||
|
@ -2130,12 +2119,14 @@ float ZoneHeapThreshold::computeZoneHeapGrowthFactorForHeapSize(
|
|||
size_t ZoneHeapThreshold::computeZoneTriggerBytes(
|
||||
float growthFactor, size_t lastBytes, JSGCInvocationKind gckind,
|
||||
const GCSchedulingTunables& tunables, const AutoLockGC& lock) {
|
||||
size_t base =
|
||||
gckind == GC_SHRINK
|
||||
? Max(lastBytes, tunables.minEmptyChunkCount(lock) * ChunkSize)
|
||||
: Max(lastBytes, tunables.gcZoneAllocThresholdBase());
|
||||
size_t baseMin = gckind == GC_SHRINK
|
||||
? tunables.minEmptyChunkCount(lock) * ChunkSize
|
||||
: tunables.gcZoneAllocThresholdBase();
|
||||
size_t base = Max(lastBytes, baseMin);
|
||||
float trigger = float(base) * growthFactor;
|
||||
return size_t(Min(float(tunables.gcMaxBytes()), trigger));
|
||||
float triggerMax =
|
||||
float(tunables.gcMaxBytes()) / tunables.nonIncrementalFactor();
|
||||
return size_t(Min(triggerMax, trigger));
|
||||
}
|
||||
|
||||
void ZoneHeapThreshold::updateAfterGC(size_t lastBytes,
|
||||
|
@ -3425,43 +3416,45 @@ void GCRuntime::maybeAllocTriggerZoneGC(Zone* zone, size_t nbytes) {
|
|||
size_t usedBytes =
|
||||
zone->zoneSize.gcBytes(); // This already includes |nbytes|.
|
||||
size_t thresholdBytes = zone->threshold.gcTriggerBytes();
|
||||
if (usedBytes >= thresholdBytes) {
|
||||
// The threshold has been surpassed, immediately trigger a GC, which
|
||||
// will be done non-incrementally.
|
||||
triggerZoneGC(zone, JS::GCReason::ALLOC_TRIGGER, usedBytes, thresholdBytes);
|
||||
if (usedBytes < thresholdBytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool wouldInterruptCollection =
|
||||
isIncrementalGCInProgress() && !zone->isCollecting();
|
||||
float zoneGCThresholdFactor =
|
||||
wouldInterruptCollection ? tunables.allocThresholdFactorAvoidInterrupt()
|
||||
: tunables.allocThresholdFactor();
|
||||
size_t niThreshold = thresholdBytes * tunables.nonIncrementalFactor();
|
||||
if (usedBytes >= niThreshold) {
|
||||
// We have passed the non-incremental threshold: immediately trigger a
|
||||
// non-incremental GC.
|
||||
triggerZoneGC(zone, JS::GCReason::ALLOC_TRIGGER, usedBytes, niThreshold);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t igcThresholdBytes = thresholdBytes * zoneGCThresholdFactor;
|
||||
// Use a higher threshold if starting a GC would reset an in-progress
|
||||
// collection.
|
||||
if (isIncrementalGCInProgress() && !zone->isCollecting() &&
|
||||
usedBytes < thresholdBytes * tunables.avoidInterruptFactor()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (usedBytes >= igcThresholdBytes) {
|
||||
// During an incremental GC, reduce the delay to the start of the next
|
||||
// incremental slice.
|
||||
if (zone->gcDelayBytes < nbytes) {
|
||||
zone->gcDelayBytes = 0;
|
||||
} else {
|
||||
zone->gcDelayBytes -= nbytes;
|
||||
}
|
||||
// During an incremental GC, reduce the delay to the start of the next
|
||||
// incremental slice.
|
||||
if (zone->gcDelayBytes < nbytes) {
|
||||
zone->gcDelayBytes = 0;
|
||||
} else {
|
||||
zone->gcDelayBytes -= nbytes;
|
||||
}
|
||||
|
||||
if (!zone->gcDelayBytes) {
|
||||
// Start or continue an in progress incremental GC. We do this
|
||||
// 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::INCREMENTAL_ALLOC_TRIGGER, usedBytes,
|
||||
igcThresholdBytes);
|
||||
if (!zone->gcDelayBytes) {
|
||||
// Start or continue an in progress incremental GC. We do this
|
||||
// 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::INCREMENTAL_ALLOC_TRIGGER, usedBytes,
|
||||
thresholdBytes);
|
||||
|
||||
// Delay the next slice until a certain amount of allocation
|
||||
// has been performed.
|
||||
zone->gcDelayBytes = tunables.zoneAllocDelayBytes();
|
||||
return;
|
||||
}
|
||||
// Delay the next slice until a certain amount of allocation
|
||||
// has been performed.
|
||||
zone->gcDelayBytes = tunables.zoneAllocDelayBytes();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3497,22 +3490,28 @@ bool GCRuntime::maybeMallocTriggerZoneGC(Zone* zone, const HeapSize& heap,
|
|||
|
||||
size_t usedBytes = heap.gcBytes();
|
||||
size_t thresholdBytes = threshold.gcTriggerBytes();
|
||||
if (usedBytes >= thresholdBytes) {
|
||||
// The threshold has been surpassed, immediately trigger a GC, which
|
||||
// will be done non-incrementally.
|
||||
triggerZoneGC(zone, reason, usedBytes, thresholdBytes);
|
||||
if (usedBytes < thresholdBytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t niThreshold = thresholdBytes * tunables.nonIncrementalFactor();
|
||||
if (usedBytes >= thresholdBytes * niThreshold) {
|
||||
// We have passed the non-incremental threshold: immediately trigger a
|
||||
// non-incremental GC.
|
||||
triggerZoneGC(zone, reason, usedBytes, niThreshold);
|
||||
return true;
|
||||
}
|
||||
|
||||
float zoneGCThresholdFactor = tunables.allocThresholdFactor();
|
||||
size_t igcThresholdBytes = thresholdBytes * zoneGCThresholdFactor;
|
||||
if (usedBytes >= igcThresholdBytes) {
|
||||
// Start or continue an in progress incremental GC.
|
||||
triggerZoneGC(zone, reason, usedBytes, igcThresholdBytes);
|
||||
return true;
|
||||
// Use a higher threshold if starting a GC would reset an in-progress
|
||||
// collection.
|
||||
if (isIncrementalGCInProgress() && !zone->isCollecting() &&
|
||||
usedBytes < thresholdBytes * tunables.avoidInterruptFactor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
// Start or continue an in progress incremental GC.
|
||||
triggerZoneGC(zone, reason, usedBytes, thresholdBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GCRuntime::triggerZoneGC(Zone* zone, JS::GCReason reason, size_t used,
|
||||
|
@ -7422,7 +7421,8 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (zone->zoneSize.gcBytes() >= zone->threshold.gcTriggerBytes()) {
|
||||
if (zone->zoneSize.gcBytes() >=
|
||||
zone->threshold.nonIncrementalTriggerBytes(tunables)) {
|
||||
CheckZoneIsScheduled(zone, reason, "GC bytes");
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::GCBytesTrigger);
|
||||
|
@ -7432,7 +7432,7 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
|
|||
}
|
||||
|
||||
if (zone->gcMallocBytes.gcBytes() >=
|
||||
zone->gcMallocThreshold.gcTriggerBytes()) {
|
||||
zone->gcMallocThreshold.nonIncrementalTriggerBytes(tunables)) {
|
||||
CheckZoneIsScheduled(zone, reason, "malloc bytes");
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::MallocBytesTrigger);
|
||||
|
@ -7441,7 +7441,8 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
|
|||
}
|
||||
}
|
||||
|
||||
if (zone->gcJitBytes.gcBytes() >= zone->gcJitThreshold.gcTriggerBytes()) {
|
||||
if (zone->gcJitBytes.gcBytes() >=
|
||||
zone->gcJitThreshold.nonIncrementalTriggerBytes(tunables)) {
|
||||
CheckZoneIsScheduled(zone, reason, "JIT code bytes");
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::JitCodeBytesTrigger);
|
||||
|
|
|
@ -355,18 +355,19 @@ class GCSchedulingTunables {
|
|||
MainThreadOrGCTaskData<size_t> gcZoneAllocThresholdBase_;
|
||||
|
||||
/*
|
||||
* JSGC_ALLOCATION_THRESHOLD_FACTOR
|
||||
* JSGC_NON_INCREMENTAL_FACTOR
|
||||
*
|
||||
* Fraction of threshold.gcBytes() which triggers an incremental GC.
|
||||
* Multiple of threshold.gcBytes() which triggers a non-incremental GC.
|
||||
*/
|
||||
UnprotectedData<float> allocThresholdFactor_;
|
||||
UnprotectedData<float> nonIncrementalFactor_;
|
||||
|
||||
/*
|
||||
* JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT
|
||||
* JSGC_AVOID_INTERRUPT_FACTOR
|
||||
*
|
||||
* The same except when doing so would interrupt an already running GC.
|
||||
* Multiple of threshold.gcBytes() which triggers a new incremental GC when
|
||||
* doing so would interrupt an ongoing incremental GC.
|
||||
*/
|
||||
UnprotectedData<float> allocThresholdFactorAvoidInterrupt_;
|
||||
UnprotectedData<float> avoidInterruptFactor_;
|
||||
|
||||
/*
|
||||
* Number of bytes to allocate between incremental slices in GCs triggered
|
||||
|
@ -488,10 +489,8 @@ class GCSchedulingTunables {
|
|||
size_t gcMinNurseryBytes() const { return gcMinNurseryBytes_; }
|
||||
size_t gcMaxNurseryBytes() const { return gcMaxNurseryBytes_; }
|
||||
size_t gcZoneAllocThresholdBase() const { return gcZoneAllocThresholdBase_; }
|
||||
double allocThresholdFactor() const { return allocThresholdFactor_; }
|
||||
double allocThresholdFactorAvoidInterrupt() const {
|
||||
return allocThresholdFactorAvoidInterrupt_;
|
||||
}
|
||||
double nonIncrementalFactor() const { return nonIncrementalFactor_; }
|
||||
double avoidInterruptFactor() const { return avoidInterruptFactor_; }
|
||||
size_t zoneAllocDelayBytes() const { return zoneAllocDelayBytes_; }
|
||||
bool isDynamicHeapGrowthEnabled() const { return dynamicHeapGrowthEnabled_; }
|
||||
const mozilla::TimeDuration& highFrequencyThreshold() const {
|
||||
|
@ -656,6 +655,9 @@ class ZoneThreshold {
|
|||
|
||||
public:
|
||||
size_t gcTriggerBytes() const { return gcTriggerBytes_; }
|
||||
size_t nonIncrementalTriggerBytes(GCSchedulingTunables& tunables) const {
|
||||
return gcTriggerBytes_ * tunables.nonIncrementalFactor();
|
||||
}
|
||||
float eagerAllocTrigger(bool highFrequencyGC) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -147,9 +147,7 @@ class ZoneAllocator : public JS::shadow::Zone,
|
|||
const js::gc::ZoneThreshold& threshold,
|
||||
JS::GCReason reason) {
|
||||
JSRuntime* rt = runtimeFromAnyThread();
|
||||
float factor = rt->gc.tunables.allocThresholdFactor();
|
||||
size_t thresholdBytes = threshold.gcTriggerBytes() * factor;
|
||||
if (heap.gcBytes() >= thresholdBytes &&
|
||||
if (heap.gcBytes() >= threshold.gcTriggerBytes() &&
|
||||
rt->heapState() == JS::HeapState::Idle) {
|
||||
gc::MaybeMallocTriggerZoneGC(rt, this, heap, threshold, reason);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ testChangeParam("lowFrequencyHeapGrowth");
|
|||
testChangeParam("dynamicHeapGrowth");
|
||||
testChangeParam("dynamicMarkSlice");
|
||||
testChangeParam("allocationThreshold");
|
||||
testChangeParam("nonIncrementalFactor");
|
||||
testChangeParam("avoidInterruptFactor");
|
||||
testChangeParam("minEmptyChunkCount");
|
||||
testChangeParam("maxEmptyChunkCount");
|
||||
testChangeParam("compactingEnabled");
|
||||
|
|
|
@ -1424,13 +1424,13 @@ pref("javascript.options.mem.gc_dynamic_heap_growth", true);
|
|||
pref("javascript.options.mem.gc_dynamic_mark_slice", true);
|
||||
|
||||
// JSGC_ALLOCATION_THRESHOLD
|
||||
pref("javascript.options.mem.gc_allocation_threshold_mb", 30);
|
||||
pref("javascript.options.mem.gc_allocation_threshold_mb", 27);
|
||||
|
||||
// JSGC_ALLOCATION_THRESHOLD_FACTOR
|
||||
pref("javascript.options.mem.gc_allocation_threshold_factor", 90);
|
||||
// JSGC_NON_INCREMENTAL_FACTOR
|
||||
pref("javascript.options.mem.gc_non_incremental_factor", 112);
|
||||
|
||||
// JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT
|
||||
pref("javascript.options.mem.gc_allocation_threshold_factor_avoid_interrupt", 90);
|
||||
// JSGC_AVOID_INTERRUPT_FACTOR
|
||||
pref("javascript.options.mem.gc_avoid_interrupt_factor", 100);
|
||||
|
||||
// JSGC_MIN_EMPTY_CHUNK_COUNT
|
||||
pref("javascript.options.mem.gc_min_empty_chunk_count", 1);
|
||||
|
|
Загрузка…
Ссылка в новой задаче