зеркало из https://github.com/mozilla/gecko-dev.git
Bug 958492 - Start an incremental GC when nearing the allocation threshold for non-incremental zone GCs, r=billm.
This commit is contained in:
Родитель
3c7249f931
Коммит
a159f4b2a3
|
@ -84,6 +84,15 @@ class GCSchedulingTunables
|
|||
*/
|
||||
size_t gcZoneAllocThresholdBase_;
|
||||
|
||||
/* Fraction of threshold.gcBytes() which triggers an incremental GC. */
|
||||
double zoneAllocThresholdFactor_;
|
||||
|
||||
/*
|
||||
* Number of bytes to allocate between incremental slices in GCs triggered
|
||||
* by the zone allocation threshold.
|
||||
*/
|
||||
size_t zoneAllocDelayBytes_;
|
||||
|
||||
/*
|
||||
* Totally disables |highFrequencyGC|, the HeapGrowthFactor, and other
|
||||
* tunables that make GC non-deterministic.
|
||||
|
@ -126,6 +135,8 @@ class GCSchedulingTunables
|
|||
GCSchedulingTunables()
|
||||
: gcMaxBytes_(0),
|
||||
gcZoneAllocThresholdBase_(30 * 1024 * 1024),
|
||||
zoneAllocThresholdFactor_(0.9),
|
||||
zoneAllocDelayBytes_(1024 * 1024),
|
||||
dynamicHeapGrowthEnabled_(false),
|
||||
highFrequencyThresholdUsec_(1000 * 1000),
|
||||
highFrequencyLowLimitBytes_(100 * 1024 * 1024),
|
||||
|
@ -140,6 +151,8 @@ class GCSchedulingTunables
|
|||
|
||||
size_t gcMaxBytes() const { return gcMaxBytes_; }
|
||||
size_t gcZoneAllocThresholdBase() const { return gcZoneAllocThresholdBase_; }
|
||||
double zoneAllocThresholdFactor() const { return zoneAllocThresholdFactor_; }
|
||||
size_t zoneAllocDelayBytes() const { return zoneAllocDelayBytes_; }
|
||||
bool isDynamicHeapGrowthEnabled() const { return dynamicHeapGrowthEnabled_; }
|
||||
uint64_t highFrequencyThresholdUsec() const { return highFrequencyThresholdUsec_; }
|
||||
uint64_t highFrequencyLowLimitBytes() const { return highFrequencyLowLimitBytes_; }
|
||||
|
|
|
@ -28,6 +28,7 @@ JS::Zone::Zone(JSRuntime *rt)
|
|||
gcMallocBytes(0),
|
||||
gcMallocGCTriggered(false),
|
||||
usage(&rt->gc.usage),
|
||||
gcDelayBytes(0),
|
||||
data(nullptr),
|
||||
isSystem(false),
|
||||
usedByExclusiveThread(false),
|
||||
|
|
|
@ -283,6 +283,10 @@ struct Zone : public JS::shadow::Zone,
|
|||
// Thresholds used to trigger GC.
|
||||
js::gc::ZoneHeapThreshold threshold;
|
||||
|
||||
// Amount of data to allocate before triggering a new incremental slice for
|
||||
// the current GC.
|
||||
size_t gcDelayBytes;
|
||||
|
||||
// Per-zone data for use by an embedder.
|
||||
void *data;
|
||||
|
||||
|
|
|
@ -971,9 +971,36 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind)
|
|||
|
||||
zone->usage.addGCArena();
|
||||
|
||||
if (!rt->isHeapCompacting() && zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) {
|
||||
if (!rt->isHeapCompacting()) {
|
||||
size_t usedBytes = zone->usage.gcBytes();
|
||||
size_t thresholdBytes = zone->threshold.gcTriggerBytes();
|
||||
size_t igcThresholdBytes = thresholdBytes * rt->gc.tunables.zoneAllocThresholdFactor();
|
||||
|
||||
if (usedBytes >= thresholdBytes) {
|
||||
// The threshold has been surpassed, immediately trigger a GC,
|
||||
// which will be done non-incrementally.
|
||||
AutoUnlockGC unlock(rt);
|
||||
rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER);
|
||||
} else if (usedBytes >= igcThresholdBytes) {
|
||||
// Reduce the delay to the start of the next incremental slice.
|
||||
if (zone->gcDelayBytes < ArenaSize)
|
||||
zone->gcDelayBytes = 0;
|
||||
else
|
||||
zone->gcDelayBytes -= ArenaSize;
|
||||
|
||||
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.
|
||||
AutoUnlockGC unlock(rt);
|
||||
rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER);
|
||||
|
||||
// Delay the next slice until a certain amount of allocation
|
||||
// has been performed.
|
||||
zone->gcDelayBytes = rt->gc.tunables.zoneAllocDelayBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aheader;
|
||||
|
@ -5675,8 +5702,13 @@ GCRuntime::gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
|||
State prevState = incrementalState;
|
||||
|
||||
if (!incremental) {
|
||||
/* If non-incremental GC was requested, reset incremental GC. */
|
||||
// Reset any in progress incremental GC if this was triggered via the
|
||||
// API. This isn't required for correctness, but sometimes during tests
|
||||
// the caller expects this GC to collect certain objects, and we need
|
||||
// to make sure to collect everything possible.
|
||||
if (reason != JS::gcreason::ALLOC_TRIGGER)
|
||||
resetIncrementalGC("requested");
|
||||
|
||||
stats.nonincremental("requested");
|
||||
budget = SliceBudget::Unlimited;
|
||||
} else {
|
||||
|
@ -5874,6 +5906,8 @@ GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64
|
|||
int64_t budget;
|
||||
if (millis)
|
||||
budget = SliceBudget::TimeBudget(millis);
|
||||
else if (reason == JS::gcreason::ALLOC_TRIGGER)
|
||||
budget = sliceBudget;
|
||||
else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled())
|
||||
budget = sliceBudget * IGC_MARK_SLICE_MULTIPLIER;
|
||||
else
|
||||
|
|
|
@ -5996,6 +5996,7 @@ main(int argc, char **argv, char **envp)
|
|||
#ifdef JSGC_GENERATIONAL
|
||||
|| !op.addBoolOption('\0', "no-ggc", "Disable Generational GC")
|
||||
#endif
|
||||
|| !op.addBoolOption('\0', "no-incremental-gc", "Disable Incremental GC")
|
||||
|| !op.addIntOption('\0', "available-memory", "SIZE",
|
||||
"Select GC settings based on available memory (MB)", 0)
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
|
@ -6132,6 +6133,17 @@ main(int argc, char **argv, char **envp)
|
|||
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
|
||||
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
|
||||
|
||||
// Set some parameters to allow incremental GC in low memory conditions,
|
||||
// as is done for the browser, except in more-deterministic builds or when
|
||||
// disabled by command line options.
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
if (!op.getBoolOption("no-incremental-gc")) {
|
||||
JS_SetGCParameter(rt, JSGC_DYNAMIC_HEAP_GROWTH, 1);
|
||||
JS_SetGCParameter(rt, JSGC_DYNAMIC_MARK_SLICE, 1);
|
||||
JS_SetGCParameter(rt, JSGC_SLICE_TIME_BUDGET, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
js::SetPreserveWrapperCallback(rt, DummyPreserveWrapperCallback);
|
||||
|
||||
result = Shell(cx, &op, envp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче