mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 19:55:39 +00:00
Bug 1386660 - Part 3: Provide code to reset SM/GC parameters. r=jonco
This commit is contained in:
parent
7b3f7718b5
commit
73cca4c47d
@ -216,25 +216,7 @@ class GCSchedulingTunables
|
||||
UnprotectedData<uint32_t> maxEmptyChunkCount_;
|
||||
|
||||
public:
|
||||
GCSchedulingTunables()
|
||||
: gcMaxBytes_(0),
|
||||
gcMaxNurseryBytes_(0),
|
||||
gcZoneAllocThresholdBase_(30 * 1024 * 1024),
|
||||
zoneAllocThresholdFactor_(0.9f),
|
||||
zoneAllocThresholdFactorAvoidInterrupt_(0.9f),
|
||||
zoneAllocDelayBytes_(1024 * 1024),
|
||||
dynamicHeapGrowthEnabled_(false),
|
||||
highFrequencyThresholdUsec_(1000 * 1000),
|
||||
highFrequencyLowLimitBytes_(100 * 1024 * 1024),
|
||||
highFrequencyHighLimitBytes_(500 * 1024 * 1024),
|
||||
highFrequencyHeapGrowthMax_(3.0),
|
||||
highFrequencyHeapGrowthMin_(1.5),
|
||||
lowFrequencyHeapGrowth_(1.5),
|
||||
dynamicMarkSliceEnabled_(false),
|
||||
refreshFrameSlicesEnabled_(true),
|
||||
minEmptyChunkCount_(1),
|
||||
maxEmptyChunkCount_(30)
|
||||
{}
|
||||
GCSchedulingTunables();
|
||||
|
||||
size_t gcMaxBytes() const { return gcMaxBytes_; }
|
||||
size_t gcMaxNurseryBytes() const { return gcMaxNurseryBytes_; }
|
||||
@ -255,6 +237,13 @@ class GCSchedulingTunables
|
||||
unsigned maxEmptyChunkCount() const { return maxEmptyChunkCount_; }
|
||||
|
||||
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, const AutoLockGC& lock);
|
||||
void resetParameter(JSGCParamKey key, const AutoLockGC& lock);
|
||||
|
||||
private:
|
||||
void setHighFrequencyLowLimit(uint64_t value);
|
||||
void setHighFrequencyHighLimit(uint64_t value);
|
||||
void setMinEmptyChunkCount(uint32_t value);
|
||||
void setMaxEmptyChunkCount(uint32_t value);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -700,6 +689,7 @@ class GCRuntime
|
||||
void setMarkStackLimit(size_t limit, AutoLockGC& lock);
|
||||
|
||||
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
|
||||
void resetParameter(JSGCParamKey key, AutoLockGC& lock);
|
||||
uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
|
||||
|
||||
MOZ_MUST_USE bool triggerGC(JS::gcreason::Reason reason);
|
||||
|
@ -1477,6 +1477,14 @@ JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value)
|
||||
MOZ_ALWAYS_TRUE(cx->runtime()->gc.setParameter(key, value, lock));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ResetGCParameter(JSContext* cx, JSGCParamKey key)
|
||||
{
|
||||
cx->runtime()->gc.waitBackgroundSweepEnd();
|
||||
AutoLockGC lock(cx->runtime());
|
||||
cx->runtime()->gc.resetParameter(key, lock);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
JS_GetGCParameter(JSContext* cx, JSGCParamKey key)
|
||||
{
|
||||
|
@ -1875,6 +1875,9 @@ typedef enum JSGCParamKey {
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ResetGCParameter(JSContext* cx, JSGCParamKey key);
|
||||
|
||||
extern JS_PUBLIC_API(uint32_t)
|
||||
JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
|
||||
|
||||
|
178
js/src/jsgc.cpp
178
js/src/jsgc.cpp
@ -1234,20 +1234,14 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
|
||||
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
|
||||
if (newLimit == UINT64_MAX)
|
||||
return false;
|
||||
highFrequencyLowLimitBytes_ = newLimit;
|
||||
if (highFrequencyLowLimitBytes_ >= highFrequencyHighLimitBytes_)
|
||||
highFrequencyHighLimitBytes_ = highFrequencyLowLimitBytes_ + 1;
|
||||
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
|
||||
setHighFrequencyLowLimit(newLimit);
|
||||
break;
|
||||
}
|
||||
case JSGC_HIGH_FREQUENCY_HIGH_LIMIT: {
|
||||
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
|
||||
if (newLimit == 0)
|
||||
return false;
|
||||
highFrequencyHighLimitBytes_ = newLimit;
|
||||
if (highFrequencyHighLimitBytes_ <= highFrequencyLowLimitBytes_)
|
||||
highFrequencyLowLimitBytes_ = highFrequencyHighLimitBytes_ - 1;
|
||||
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
|
||||
setHighFrequencyHighLimit(newLimit);
|
||||
break;
|
||||
}
|
||||
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX: {
|
||||
@ -1284,16 +1278,10 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
|
||||
gcZoneAllocThresholdBase_ = value * 1024 * 1024;
|
||||
break;
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
minEmptyChunkCount_ = value;
|
||||
if (minEmptyChunkCount_ > maxEmptyChunkCount_)
|
||||
maxEmptyChunkCount_ = minEmptyChunkCount_;
|
||||
MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_);
|
||||
setMinEmptyChunkCount(value);
|
||||
break;
|
||||
case JSGC_MAX_EMPTY_CHUNK_COUNT:
|
||||
maxEmptyChunkCount_ = value;
|
||||
if (minEmptyChunkCount_ > maxEmptyChunkCount_)
|
||||
minEmptyChunkCount_ = maxEmptyChunkCount_;
|
||||
MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_);
|
||||
setMaxEmptyChunkCount(value);
|
||||
break;
|
||||
case JSGC_REFRESH_FRAME_SLICES_ENABLED:
|
||||
refreshFrameSlicesEnabled_ = value != 0;
|
||||
@ -1305,6 +1293,164 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GCSchedulingTunables::setHighFrequencyLowLimit(uint64_t newLimit)
|
||||
{
|
||||
highFrequencyLowLimitBytes_ = newLimit;
|
||||
if (highFrequencyLowLimitBytes_ >= highFrequencyHighLimitBytes_)
|
||||
highFrequencyHighLimitBytes_ = highFrequencyLowLimitBytes_ + 1;
|
||||
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
|
||||
}
|
||||
|
||||
void
|
||||
GCSchedulingTunables::setHighFrequencyHighLimit(uint64_t newLimit)
|
||||
{
|
||||
highFrequencyHighLimitBytes_ = newLimit;
|
||||
if (highFrequencyHighLimitBytes_ <= highFrequencyLowLimitBytes_)
|
||||
highFrequencyLowLimitBytes_ = highFrequencyHighLimitBytes_ - 1;
|
||||
MOZ_ASSERT(highFrequencyHighLimitBytes_ > highFrequencyLowLimitBytes_);
|
||||
}
|
||||
|
||||
void
|
||||
GCSchedulingTunables::setMinEmptyChunkCount(uint32_t value)
|
||||
{
|
||||
minEmptyChunkCount_ = value;
|
||||
if (minEmptyChunkCount_ > maxEmptyChunkCount_)
|
||||
maxEmptyChunkCount_ = minEmptyChunkCount_;
|
||||
MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_);
|
||||
}
|
||||
|
||||
void
|
||||
GCSchedulingTunables::setMaxEmptyChunkCount(uint32_t value)
|
||||
{
|
||||
maxEmptyChunkCount_ = value;
|
||||
if (minEmptyChunkCount_ > maxEmptyChunkCount_)
|
||||
minEmptyChunkCount_ = maxEmptyChunkCount_;
|
||||
MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_);
|
||||
}
|
||||
|
||||
static const size_t GCZoneAllocThresholdBaseDefault = 30 * 1024 * 1024;
|
||||
static const float ZoneAllocThresholdFactorDefault = 0.9f;
|
||||
static const float ZoneAllocThresholdFactorAvoidInterruptDefault = 0.9f;
|
||||
static const size_t ZoneAllocDelayBytesDefault = 1024 * 1024;
|
||||
static const bool DynamicHeapGrowthEnabledDefault = false;
|
||||
static const uint64_t HighFrequencyThresholdUsecDefault = 1000000;
|
||||
static const uint64_t HighFrequencyLowLimitBytesDefault = 100 * 1024 * 1024;
|
||||
static const uint64_t HighFrequencyHighLimitBytesDefault = 500 * 1024 * 1024;
|
||||
static const double HighFrequencyHeapGrowthMaxDefault = 3.0;
|
||||
static const double HighFrequencyHeapGrowthMinDefault = 1.5;
|
||||
static const double LowFrequencyHeapGrowthDefault = 1.5;
|
||||
static const bool DynamicMarkSliceEnabledDefault = false;
|
||||
static const bool RefreshFrameSlicesEnabledDefault = true;
|
||||
static const uint32_t MinEmptyChunkCountDefault = 1;
|
||||
static const uint32_t MaxEmptyChunkCountDefault = 30;
|
||||
|
||||
GCSchedulingTunables::GCSchedulingTunables()
|
||||
: gcMaxBytes_(0),
|
||||
gcMaxNurseryBytes_(0),
|
||||
gcZoneAllocThresholdBase_(GCZoneAllocThresholdBaseDefault),
|
||||
zoneAllocThresholdFactor_(ZoneAllocThresholdFactorDefault),
|
||||
zoneAllocThresholdFactorAvoidInterrupt_(
|
||||
ZoneAllocThresholdFactorAvoidInterruptDefault),
|
||||
zoneAllocDelayBytes_(ZoneAllocDelayBytesDefault),
|
||||
dynamicHeapGrowthEnabled_(DynamicHeapGrowthEnabledDefault),
|
||||
highFrequencyThresholdUsec_(HighFrequencyThresholdUsecDefault),
|
||||
highFrequencyLowLimitBytes_(HighFrequencyLowLimitBytesDefault),
|
||||
highFrequencyHighLimitBytes_(HighFrequencyHighLimitBytesDefault),
|
||||
highFrequencyHeapGrowthMax_(HighFrequencyHeapGrowthMaxDefault),
|
||||
highFrequencyHeapGrowthMin_(HighFrequencyHeapGrowthMinDefault),
|
||||
lowFrequencyHeapGrowth_(LowFrequencyHeapGrowthDefault),
|
||||
dynamicMarkSliceEnabled_(DynamicMarkSliceEnabledDefault),
|
||||
refreshFrameSlicesEnabled_(RefreshFrameSlicesEnabledDefault),
|
||||
minEmptyChunkCount_(MinEmptyChunkCountDefault),
|
||||
maxEmptyChunkCount_(MaxEmptyChunkCountDefault)
|
||||
{}
|
||||
|
||||
void
|
||||
GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock)
|
||||
{
|
||||
switch (key) {
|
||||
case JSGC_MAX_MALLOC_BYTES:
|
||||
setMaxMallocBytes(0xffffffff);
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
|
||||
zone->setGCMaxMallocBytes(maxMallocBytesAllocated() * 0.9);
|
||||
break;
|
||||
case JSGC_SLICE_TIME_BUDGET:
|
||||
defaultTimeBudget_ =
|
||||
static_cast<int64_t>(SliceBudget::UnlimitedTimeBudget);
|
||||
break;
|
||||
case JSGC_MARK_STACK_LIMIT:
|
||||
setMarkStackLimit(size_t(-1), lock);
|
||||
break;
|
||||
case JSGC_MODE:
|
||||
mode = JSGC_MODE_INCREMENTAL;
|
||||
break;
|
||||
case JSGC_COMPACTING_ENABLED:
|
||||
compactingEnabled = true;
|
||||
break;
|
||||
default:
|
||||
tunables.resetParameter(key, lock);
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
zone->threshold.updateAfterGC(zone->usage.gcBytes(), GC_NORMAL,
|
||||
tunables, schedulingState, lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GCSchedulingTunables::resetParameter(JSGCParamKey key, const AutoLockGC& lock)
|
||||
{
|
||||
switch(key) {
|
||||
case JSGC_MAX_BYTES:
|
||||
gcMaxBytes_ = 0xffffffff;
|
||||
break;
|
||||
case JSGC_MAX_NURSERY_BYTES:
|
||||
gcMaxNurseryBytes_ = JS::DefaultNurseryBytes;
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
|
||||
highFrequencyThresholdUsec_ = HighFrequencyThresholdUsecDefault;
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
|
||||
setHighFrequencyLowLimit(HighFrequencyLowLimitBytesDefault);
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
|
||||
setHighFrequencyHighLimit(HighFrequencyHighLimitBytesDefault);
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
|
||||
highFrequencyHeapGrowthMax_ = HighFrequencyHeapGrowthMaxDefault;
|
||||
MOZ_ASSERT(highFrequencyHeapGrowthMax_ / 0.85 > 1.0);
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
|
||||
highFrequencyHeapGrowthMin_ = HighFrequencyHeapGrowthMinDefault;
|
||||
MOZ_ASSERT(highFrequencyHeapGrowthMin_ / 0.85 > 1.0);
|
||||
break;
|
||||
case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
|
||||
lowFrequencyHeapGrowth_ = LowFrequencyHeapGrowthDefault;
|
||||
MOZ_ASSERT(lowFrequencyHeapGrowth_ / 0.9 > 1.0);
|
||||
break;
|
||||
case JSGC_DYNAMIC_HEAP_GROWTH:
|
||||
dynamicHeapGrowthEnabled_ = DynamicHeapGrowthEnabledDefault;
|
||||
break;
|
||||
case JSGC_DYNAMIC_MARK_SLICE:
|
||||
dynamicMarkSliceEnabled_ = DynamicMarkSliceEnabledDefault;
|
||||
break;
|
||||
case JSGC_ALLOCATION_THRESHOLD:
|
||||
gcZoneAllocThresholdBase_ = GCZoneAllocThresholdBaseDefault;
|
||||
break;
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
setMinEmptyChunkCount(MinEmptyChunkCountDefault);
|
||||
break;
|
||||
case JSGC_MAX_EMPTY_CHUNK_COUNT:
|
||||
setMaxEmptyChunkCount(MaxEmptyChunkCountDefault);
|
||||
break;
|
||||
case JSGC_REFRESH_FRAME_SLICES_ENABLED:
|
||||
refreshFrameSlicesEnabled_ = RefreshFrameSlicesEnabledDefault;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown GC parameter.");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user