diff --git a/memory/build/PHC.cpp b/memory/build/PHC.cpp index f6e02b2c22d2..94cb5596a501 100644 --- a/memory/build/PHC.cpp +++ b/memory/build/PHC.cpp @@ -343,7 +343,15 @@ static const Time kMaxTime = ~(Time(0)); constexpr Delay Rnd64ToDelay(Delay aAvgDelay, uint64_t aRnd) { MOZ_ASSERT(IsPowerOfTwo(aAvgDelay), "must be a power of two"); - return (aRnd & (aAvgDelay * 2 - 1)) + 1; + return (aRnd & (uint64_t(aAvgDelay) * 2 - 1)) + 1; +} + +static Delay CheckProbability(int64_t aProb) { + // Limit delays calculated from prefs to 0x80000000, this is the largest + // power-of-two that fits in a Delay since it is a uint32_t. + // The minimum is 2 that way not every allocation goes straight to PHC. + return RoundUpPow2( + std::min(std::max(aProb, int64_t(2)), int64_t(0x80000000))); } // Maps a pointer to a PHC-specific structure: @@ -863,6 +871,15 @@ class GMut { mPhcState = aState; } + void SetProbabilities(int64_t aAvgDelayFirst, int64_t aAvgDelayNormal, + int64_t aAvgDelayPageReuse) { + MutexAutoLock lock(GMut::sMutex); + + mAvgFirstAllocDelay = CheckProbability(aAvgDelayFirst); + mAvgAllocDelay = CheckProbability(aAvgDelayNormal); + mAvgPageReuseDelay = CheckProbability(aAvgDelayPageReuse); + } + private: template uint64_t RandomSeed() { @@ -1807,4 +1824,14 @@ void SetPHCState(PHCState aState) { gMut->SetState(aState); } + +void SetPHCProbabilities(int64_t aAvgDelayFirst, int64_t aAvgDelayNormal, + int64_t aAvgDelayPageReuse) { + if (!maybe_init()) { + return; + } + + gMut->SetProbabilities(aAvgDelayFirst, aAvgDelayNormal, aAvgDelayPageReuse); +} + } // namespace mozilla::phc diff --git a/memory/build/PHC.h b/memory/build/PHC.h index ce5f7994e2d2..78820a5cf3f3 100644 --- a/memory/build/PHC.h +++ b/memory/build/PHC.h @@ -129,6 +129,10 @@ enum PHCState { MOZ_JEMALLOC_API void SetPHCState(PHCState aState); +MOZ_JEMALLOC_API void SetPHCProbabilities(int64_t aAvgDelayFirst, + int64_t aAvgDelayNormal, + int64_t aAvgDelayPageReuse); + struct MemoryUsage { // The amount of memory used for PHC metadata, eg information about each // allocation including stacks. diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index d4e9f1fbd0d7..c1e33bf3cb19 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -11051,6 +11051,21 @@ value: 8000 mirror: always +- name: memory.phc.avg_delay.first + type: uint32_t + value: 65536 + mirror: always + +- name: memory.phc.avg_delay.normal + type: uint32_t + value: 16384 + mirror: always + +- name: memory.phc.avg_delay.page_reuse + type: uint32_t + value: 262144 + mirror: always + #--------------------------------------------------------------------------- # Prefs starting with "midi." #--------------------------------------------------------------------------- diff --git a/toolkit/components/nimbus/FeatureManifest.yaml b/toolkit/components/nimbus/FeatureManifest.yaml index 376c4f110015..9dd069455aa8 100644 --- a/toolkit/components/nimbus/FeatureManifest.yaml +++ b/toolkit/components/nimbus/FeatureManifest.yaml @@ -2288,6 +2288,24 @@ phc: setPref: branch: user pref: memory.phc.min_ram_mb + phcAvgDelayFirst: + description: The delay before the first PHC allocation + type: int + setPref: + branch: user + pref: memory.phc.avg_delay.first + phcAvgDelayNormal: + description: The delay between PHC allocations + type: int + setPref: + branch: user + pref: memory.phc.avg_delay.normal + phcAvgDelayPageReuse: + description: The delay before reusing a PHC page + type: int + setPref: + branch: user + pref: memory.phc.avg_delay.page_reuse mailto: description: Prefs to control aspects of the mailto handler diff --git a/xpcom/base/PHCManager.cpp b/xpcom/base/PHCManager.cpp index 7caccddf7d6f..f8124312f5f5 100644 --- a/xpcom/base/PHCManager.cpp +++ b/xpcom/base/PHCManager.cpp @@ -19,6 +19,9 @@ using namespace phc; static const char kPHCEnabledPref[] = "memory.phc.enabled"; static const char kPHCMinRamMBPref[] = "memory.phc.min_ram_mb"; +static const char kPHCAvgDelayFirst[] = "memory.phc.avg_delay.first"; +static const char kPHCAvgDelayNormal[] = "memory.phc.avg_delay.normal"; +static const char kPHCAvgDelayPageRuse[] = "memory.phc.avg_delay.page_reuse"; // True if PHC has ever been enabled for this process. static bool sWasPHCEnabled = false; @@ -32,6 +35,12 @@ static void UpdatePHCState() { // slightly lower actual RAM available after some hardware devices // reserve some. if (StaticPrefs::memory_phc_enabled() && mem_size >= min_mem_size) { + // Set PHC probablities before enabling PHC so that the first allocation + // delay gets used. + SetPHCProbabilities(StaticPrefs::memory_phc_avg_delay_first(), + StaticPrefs::memory_phc_avg_delay_normal(), + StaticPrefs::memory_phc_avg_delay_page_reuse()); + SetPHCState(Enabled); sWasPHCEnabled = true; } else { @@ -41,7 +50,10 @@ static void UpdatePHCState() { static void PrefChangeCallback(const char* aPrefName, void* aNull) { MOZ_ASSERT((0 == strcmp(aPrefName, kPHCEnabledPref)) || - (0 == strcmp(aPrefName, kPHCMinRamMBPref))); + (0 == strcmp(aPrefName, kPHCMinRamMBPref)) || + (0 == strcmp(aPrefName, kPHCAvgDelayFirst)) || + (0 == strcmp(aPrefName, kPHCAvgDelayNormal)) || + (0 == strcmp(aPrefName, kPHCAvgDelayPageRuse))); UpdatePHCState(); } @@ -49,6 +61,9 @@ static void PrefChangeCallback(const char* aPrefName, void* aNull) { void InitPHCState() { Preferences::RegisterCallback(PrefChangeCallback, kPHCEnabledPref); Preferences::RegisterCallback(PrefChangeCallback, kPHCMinRamMBPref); + Preferences::RegisterCallback(PrefChangeCallback, kPHCAvgDelayFirst); + Preferences::RegisterCallback(PrefChangeCallback, kPHCAvgDelayNormal); + Preferences::RegisterCallback(PrefChangeCallback, kPHCAvgDelayPageRuse); UpdatePHCState(); }