зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1522187 - Decide string pretenuring base on pretenure rate. r=jonco
Choose the string pretenuring threshold as 0.55, as it's the most common pretured rate when the number of strings pretenured exceeds 30,000 in JetStream2 benchmark. (about 0.55~0.57 in my tests). However this threshold shouldn't have any major impact on benchmarks like Octane, JetStream2 and Kraken, as in these benchmarks when the pretenuring condition is met, the tenured rate is 99%. Differential Revision: https://phabricator.services.mozilla.com/D92762
This commit is contained in:
Родитель
76c3e94c96
Коммит
8c9a4c00bb
|
@ -379,6 +379,12 @@ typedef enum JSGCParamKey {
|
|||
*/
|
||||
JSGC_HELPER_THREAD_COUNT = 41,
|
||||
|
||||
/**
|
||||
* If the percentage of the tenured strings exceeds this threshold, string
|
||||
* will be allocated in tenured heap instead. (Default is allocated in
|
||||
* nursery.)
|
||||
*/
|
||||
JSGC_PRETENURE_STRING_THRESHOLD = 42,
|
||||
} JSGCParamKey;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1527,6 +1527,8 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
|
|||
return uint32_t(tunables.pretenureThreshold() * 100);
|
||||
case JSGC_PRETENURE_GROUP_THRESHOLD:
|
||||
return tunables.pretenureGroupThreshold();
|
||||
case JSGC_PRETENURE_STRING_THRESHOLD:
|
||||
return uint32_t(tunables.pretenureStringThreshold() * 100);
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
return tunables.minLastDitchGCPeriod().ToSeconds();
|
||||
case JSGC_ZONE_ALLOC_DELAY_KB:
|
||||
|
|
|
@ -475,6 +475,14 @@ Cell* js::Nursery::allocateCell(Zone* zone, size_t size, JS::TraceKind kind) {
|
|||
return cell;
|
||||
}
|
||||
|
||||
Cell* js::Nursery::allocateString(JS::Zone* zone, size_t size) {
|
||||
Cell* cell = allocateCell(zone, size, JS::TraceKind::String);
|
||||
if (cell) {
|
||||
zone->nurseryAllocatedStrings++;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
inline void* js::Nursery::allocate(size_t size) {
|
||||
MOZ_ASSERT(isEnabled());
|
||||
MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
|
||||
|
@ -1274,8 +1282,18 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason,
|
|||
uint32_t numBigIntsTenured = 0;
|
||||
uint32_t numNurseryBigIntRealmsDisabled = 0;
|
||||
for (ZonesIter zone(gc, SkipAtoms); !zone.done(); zone.next()) {
|
||||
bool disableNurseryStrings = pretenureStr && zone->allocNurseryStrings &&
|
||||
zone->tenuredStrings >= 30 * 1000;
|
||||
// For some tests in JetStream2 and Kranken, the tenuredRate is high but the
|
||||
// number of allocated strings is low. So we calculate the tenuredRate only
|
||||
// if the number of string allocations is enough.
|
||||
bool allocThreshold = zone->nurseryAllocatedStrings > 30000;
|
||||
double tenuredRate = allocThreshold
|
||||
? double(zone->tenuredStrings) /
|
||||
double(zone->nurseryAllocatedStrings)
|
||||
: 0.0;
|
||||
|
||||
bool disableNurseryStrings =
|
||||
pretenureStr && zone->allocNurseryStrings &&
|
||||
tenuredRate > tunables().pretenureStringThreshold();
|
||||
bool disableNurseryBigInts = pretenureBigInt && zone->allocNurseryBigInts &&
|
||||
zone->tenuredBigInts >= 30 * 1000;
|
||||
if (disableNurseryStrings || disableNurseryBigInts) {
|
||||
|
@ -1310,6 +1328,7 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason,
|
|||
zone->tenuredStrings = 0;
|
||||
numBigIntsTenured += zone->tenuredBigInts;
|
||||
zone->tenuredBigInts = 0;
|
||||
zone->nurseryAllocatedStrings = 0;
|
||||
}
|
||||
session.reset(); // End the minor GC session, if running one.
|
||||
stats().setStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED,
|
||||
|
|
|
@ -246,9 +246,7 @@ class Nursery {
|
|||
gc::Cell* allocateBigInt(JS::Zone* zone, size_t size) {
|
||||
return allocateCell(zone, size, JS::TraceKind::BigInt);
|
||||
}
|
||||
gc::Cell* allocateString(JS::Zone* zone, size_t size) {
|
||||
return allocateCell(zone, size, JS::TraceKind::String);
|
||||
}
|
||||
gc::Cell* allocateString(JS::Zone* zone, size_t size);
|
||||
|
||||
static size_t nurseryCellHeaderSize() {
|
||||
return sizeof(gc::NurseryCellHeader);
|
||||
|
|
|
@ -63,6 +63,7 @@ GCSchedulingTunables::GCSchedulingTunables()
|
|||
TuningDefaults::NurseryFreeThresholdForIdleCollectionFraction),
|
||||
pretenureThreshold_(TuningDefaults::PretenureThreshold),
|
||||
pretenureGroupThreshold_(TuningDefaults::PretenureGroupThreshold),
|
||||
pretenureStringThreshold_(TuningDefaults::PretenureStringThreshold),
|
||||
minLastDitchGCPeriod_(
|
||||
TimeDuration::FromSeconds(TuningDefaults::MinLastDitchGCPeriod)),
|
||||
mallocThresholdBase_(TuningDefaults::MallocThresholdBase),
|
||||
|
@ -192,6 +193,13 @@ bool GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value,
|
|||
}
|
||||
pretenureGroupThreshold_ = value;
|
||||
break;
|
||||
case JSGC_PRETENURE_STRING_THRESHOLD:
|
||||
// 100 disables pretenuring
|
||||
if (value == 0 || value > 100) {
|
||||
return false;
|
||||
}
|
||||
pretenureStringThreshold_ = value / 100.0;
|
||||
break;
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
minLastDitchGCPeriod_ = TimeDuration::FromSeconds(value);
|
||||
break;
|
||||
|
@ -333,6 +341,9 @@ void GCSchedulingTunables::resetParameter(JSGCParamKey key,
|
|||
case JSGC_PRETENURE_GROUP_THRESHOLD:
|
||||
pretenureGroupThreshold_ = TuningDefaults::PretenureGroupThreshold;
|
||||
break;
|
||||
case JSGC_PRETENURE_STRING_THRESHOLD:
|
||||
pretenureStringThreshold_ = TuningDefaults::PretenureStringThreshold;
|
||||
break;
|
||||
case JSGC_MIN_LAST_DITCH_GC_PERIOD:
|
||||
minLastDitchGCPeriod_ =
|
||||
TimeDuration::FromSeconds(TuningDefaults::MinLastDitchGCPeriod);
|
||||
|
|
|
@ -412,6 +412,9 @@ static const double PretenureThreshold = 0.6;
|
|||
/* JSGC_PRETENURE_GROUP_THRESHOLD */
|
||||
static const double PretenureGroupThreshold = 3000;
|
||||
|
||||
/* JSGC_PRETENURE_STRING_THRESHOLD */
|
||||
static const double PretenureStringThreshold = 0.55;
|
||||
|
||||
/* JSGC_MIN_LAST_DITCH_GC_PERIOD */
|
||||
static const auto MinLastDitchGCPeriod = 60; // in seconds
|
||||
|
||||
|
@ -549,6 +552,15 @@ class GCSchedulingTunables {
|
|||
*/
|
||||
UnprotectedData<uint32_t> pretenureGroupThreshold_;
|
||||
|
||||
/*
|
||||
* JSGC_PRETENURE_STRING_THRESHOLD
|
||||
*
|
||||
* If the percentage of the tenured strings exceeds this threshold, string
|
||||
* will be allocated in tenured heap instead. (Default is allocated in
|
||||
* nursery.)
|
||||
*/
|
||||
MainThreadData<double> pretenureStringThreshold_;
|
||||
|
||||
/*
|
||||
* JSGC_MIN_LAST_DITCH_GC_PERIOD
|
||||
*
|
||||
|
@ -611,6 +623,7 @@ class GCSchedulingTunables {
|
|||
bool attemptPretenuring() const { return pretenureThreshold_ < 1.0; }
|
||||
double pretenureThreshold() const { return pretenureThreshold_; }
|
||||
uint32_t pretenureGroupThreshold() const { return pretenureGroupThreshold_; }
|
||||
double pretenureStringThreshold() const { return pretenureStringThreshold_; }
|
||||
|
||||
mozilla::TimeDuration minLastDitchGCPeriod() const {
|
||||
return minLastDitchGCPeriod_;
|
||||
|
|
|
@ -150,6 +150,7 @@ JS::Zone::Zone(JSRuntime* rt)
|
|||
data(this, nullptr),
|
||||
tenuredStrings(this, 0),
|
||||
tenuredBigInts(this, 0),
|
||||
nurseryAllocatedStrings(this, 0),
|
||||
allocNurseryStrings(this, true),
|
||||
allocNurseryBigInts(this, true),
|
||||
suppressAllocationMetadataBuilder(this, false),
|
||||
|
|
|
@ -202,6 +202,8 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
js::ZoneData<uint32_t> tenuredStrings;
|
||||
js::ZoneData<uint32_t> tenuredBigInts;
|
||||
|
||||
js::ZoneOrIonCompileData<uint64_t> nurseryAllocatedStrings;
|
||||
|
||||
js::ZoneData<bool> allocNurseryStrings;
|
||||
js::ZoneData<bool> allocNurseryBigInts;
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ class CompileRuntime {
|
|||
};
|
||||
|
||||
class CompileZone {
|
||||
friend class MacroAssembler;
|
||||
JS::Zone* zone();
|
||||
|
||||
public:
|
||||
|
|
|
@ -823,6 +823,8 @@ void MacroAssembler::nurseryAllocateString(Register result, Register temp,
|
|||
// with the nursery's end will always fail in such cases.
|
||||
|
||||
CompileZone* zone = GetJitContext()->realm()->zone();
|
||||
uint64_t* allocStrsPtr = &zone->zone()->nurseryAllocatedStrings.ref();
|
||||
inc64(AbsoluteAddress(allocStrsPtr));
|
||||
size_t thingSize = gc::Arena::thingSize(allocKind);
|
||||
|
||||
bumpPointerAllocate(result, temp, fail, zone,
|
||||
|
|
Загрузка…
Ссылка в новой задаче