Bug 1827621 - Add a mininum heap size threashold at which to use parallel marking r=sfink

Benchmark results show that using parallel marking is not always a win for
small heaps, so add a threshold for its use.

This is set to 10MB, which will result in using parallel marking ~70% of the
time.

This parameter is set to zero for jit-tests and shell js tests so we get test
coverage where heap sizes are expected to be small (and maximum performance is
not a goal).

Differential Revision: https://phabricator.services.mozilla.com/D175249
This commit is contained in:
Jon Coppeard 2023-04-13 16:38:11 +00:00
Родитель f77fa8f135
Коммит 66adc8077b
9 изменённых файлов: 95 добавлений и 50 удалений

Просмотреть файл

@ -482,6 +482,13 @@ typedef enum JSGCParamKey {
* Default: 0 (no effect).
*/
JSGC_MARKING_THREAD_COUNT = 49,
/**
* The heap size above which to use parallel marking.
*
* Default: ParallelMarkingThresholdKB
*/
JSGC_PARALLEL_MARKING_THRESHOLD_KB = 50,
} JSGCParamKey;
/*

Просмотреть файл

@ -1274,6 +1274,8 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
return tunables.mallocThresholdBase() / 1024 / 1024;
case JSGC_URGENT_THRESHOLD_MB:
return tunables.urgentThresholdBytes() / 1024 / 1024;
case JSGC_PARALLEL_MARKING_THRESHOLD_KB:
return tunables.parallelMarkingThresholdBytes() / 1024;
case JSGC_CHUNK_BYTES:
return ChunkSize;
case JSGC_HELPER_THREAD_RATIO:
@ -2987,7 +2989,8 @@ inline bool GCRuntime::canMarkInParallel() const {
}
#endif
return markers.length() > 1;
return markers.length() > 1 && stats().initialCollectedBytes() >=
tunables.parallelMarkingThresholdBytes();
}
IncrementalProgress GCRuntime::markUntilBudgetExhausted(

Просмотреть файл

@ -35,54 +35,55 @@ class TenuredChunk;
} /* namespace gc */
// Define name, key and writability for the GC parameters.
#define FOR_EACH_GC_PARAM(_) \
_("maxBytes", JSGC_MAX_BYTES, true) \
_("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
_("gcBytes", JSGC_BYTES, false) \
_("nurseryBytes", JSGC_NURSERY_BYTES, false) \
_("gcNumber", JSGC_NUMBER, false) \
_("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \
_("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \
_("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \
_("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
_("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \
_("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \
_("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \
true) \
_("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \
true) \
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \
_("balancedHeapLimitsEnabled", JSGC_BALANCED_HEAP_LIMITS_ENABLED, true) \
_("heapGrowthFactor", JSGC_HEAP_GROWTH_FACTOR, true) \
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
_("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \
_("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
_("parallelMarkingEnabled", JSGC_PARALLEL_MARKING_ENABLED, true) \
_("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \
_("nurseryFreeThresholdForIdleCollection", \
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION, true) \
_("nurseryFreeThresholdForIdleCollectionPercent", \
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT, true) \
_("nurseryTimeoutForIdleCollectionMS", \
JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS, true) \
_("pretenureThreshold", JSGC_PRETENURE_THRESHOLD, true) \
_("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \
_("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \
_("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \
_("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \
_("chunkBytes", JSGC_CHUNK_BYTES, false) \
_("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \
_("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \
_("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \
_("markingThreadCount", JSGC_MARKING_THREAD_COUNT, true) \
#define FOR_EACH_GC_PARAM(_) \
_("maxBytes", JSGC_MAX_BYTES, true) \
_("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
_("gcBytes", JSGC_BYTES, false) \
_("nurseryBytes", JSGC_NURSERY_BYTES, false) \
_("gcNumber", JSGC_NUMBER, false) \
_("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \
_("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \
_("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \
_("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
_("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \
_("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \
_("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \
true) \
_("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \
true) \
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \
_("balancedHeapLimitsEnabled", JSGC_BALANCED_HEAP_LIMITS_ENABLED, true) \
_("heapGrowthFactor", JSGC_HEAP_GROWTH_FACTOR, true) \
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
_("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \
_("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
_("parallelMarkingEnabled", JSGC_PARALLEL_MARKING_ENABLED, true) \
_("parallelMarkingThresholdKB", JSGC_PARALLEL_MARKING_THRESHOLD_KB, true) \
_("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \
_("nurseryFreeThresholdForIdleCollection", \
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION, true) \
_("nurseryFreeThresholdForIdleCollectionPercent", \
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT, true) \
_("nurseryTimeoutForIdleCollectionMS", \
JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS, true) \
_("pretenureThreshold", JSGC_PRETENURE_THRESHOLD, true) \
_("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \
_("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \
_("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \
_("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \
_("chunkBytes", JSGC_CHUNK_BYTES, false) \
_("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \
_("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \
_("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \
_("markingThreadCount", JSGC_MARKING_THREAD_COUNT, true) \
_("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false)
// Get the key and writability give a GC parameter name.

Просмотреть файл

@ -413,6 +413,7 @@ class GCRuntime {
// Internal public interface
ZoneVector& zones() { return zones_.ref(); }
gcstats::Statistics& stats() { return stats_.ref(); }
const gcstats::Statistics& stats() const { return stats_.ref(); }
State state() const { return incrementalState; }
bool isHeapCompacting() const { return state() == State::Compact; }
bool isForegroundSweeping() const { return state() == State::Sweep; }

Просмотреть файл

@ -76,7 +76,9 @@ GCSchedulingTunables::GCSchedulingTunables()
minLastDitchGCPeriod_(
TimeDuration::FromSeconds(TuningDefaults::MinLastDitchGCPeriod)),
mallocThresholdBase_(TuningDefaults::MallocThresholdBase),
urgentThresholdBytes_(TuningDefaults::UrgentThresholdBytes) {}
urgentThresholdBytes_(TuningDefaults::UrgentThresholdBytes),
parallelMarkingThresholdBytes_(
TuningDefaults::ParallelMarkingThresholdBytes) {}
bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value) {
// Limit various parameters to reasonable levels to catch errors.
@ -251,6 +253,14 @@ bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value) {
urgentThresholdBytes_ = threshold;
break;
}
case JSGC_PARALLEL_MARKING_THRESHOLD_KB: {
size_t threshold;
if (!kilobytesToBytes(value, &threshold)) {
return false;
}
parallelMarkingThresholdBytes_ = threshold;
break;
}
default:
MOZ_CRASH("Unknown GC parameter.");
}
@ -406,6 +416,10 @@ void GCSchedulingTunables::resetParameter(JSGCParamKey key) {
case JSGC_URGENT_THRESHOLD_MB:
urgentThresholdBytes_ = TuningDefaults::UrgentThresholdBytes;
break;
case JSGC_PARALLEL_MARKING_THRESHOLD_KB:
parallelMarkingThresholdBytes_ =
TuningDefaults::ParallelMarkingThresholdBytes;
break;
default:
MOZ_CRASH("Unknown GC parameter.");
}

Просмотреть файл

@ -452,6 +452,9 @@ static const size_t MaxHelperThreads = 8;
/* JSGC_URGENT_THRESHOLD_MB */
static const size_t UrgentThresholdBytes = 16 * 1024 * 1024;
/* JSGC_PARALLEL_MARKING_THRESHOLD_KB */
static const size_t ParallelMarkingThresholdBytes = 10 * 1024 * 1024;
} // namespace TuningDefaults
/*
@ -617,6 +620,11 @@ class GCSchedulingTunables {
*/
MainThreadData<size_t> urgentThresholdBytes_;
/*
* JSGC_PARALLEL_MARKING_THRESHOLD_KB
*/
MainThreadData<size_t> parallelMarkingThresholdBytes_;
public:
GCSchedulingTunables();
@ -671,6 +679,10 @@ class GCSchedulingTunables {
size_t urgentThresholdBytes() const { return urgentThresholdBytes_; }
size_t parallelMarkingThresholdBytes() const {
return parallelMarkingThresholdBytes_;
}
[[nodiscard]] bool setParameter(JSGCParamKey key, uint32_t value);
void resetParameter(JSGCParamKey key);

Просмотреть файл

@ -24,3 +24,6 @@ for (const name of ["gczeal",
}
hasFunction[name] = present;
}
// Set the minimum heap size for parallel marking to zero for testing purposes.
gcparam('parallelMarkingThresholdKB', 0);

Просмотреть файл

@ -55,6 +55,7 @@ testChangeParam("compactingEnabled");
testChangeParam("mallocThresholdBase");
testChangeParam("urgentThreshold");
testChangeParam("nurseryTimeoutForIdleCollectionMS");
testChangeParam("parallelMarkingThresholdKB");
testMBParamValue("smallHeapSizeMax");
testMBParamValue("largeHeapSizeMin");

Просмотреть файл

@ -578,4 +578,7 @@
shellOptionsClear();
})(this);
// Set the minimum heap size for parallel marking to zero for testing purposes.
gcparam('parallelMarkingThresholdKB', 0);
var DESCRIPTION;