Bug 1716727 - [3/3] make stalling behavior conditional on process type r=glandium

For now, make Set_XREProcessType set a flag in mozjemalloc to avoid
stalling repeatedly in auxiliary processes.

Differential Revision: https://phabricator.services.mozilla.com/D151332
This commit is contained in:
Ray Kraesig 2022-07-27 19:54:36 +00:00
parent 44a45dc8a5
commit a63e2430bf
3 changed files with 49 additions and 10 deletions

View File

@ -1366,6 +1366,13 @@ static inline void ApplyZeroOrJunk(void* aPtr, size_t aSize) {
// Experiment under bug 1716727. (See ./moz.build for details.) // Experiment under bug 1716727. (See ./moz.build for details.)
#ifdef XP_WIN #ifdef XP_WIN
// Whether the current process should always stall, or only stall once.
static bool sShouldAlwaysStall = true;
MOZ_JEMALLOC_API void mozjemalloc_experiment_set_always_stall(bool aVal) {
sShouldAlwaysStall = aVal;
}
# ifdef MOZ_STALL_ON_OOM # ifdef MOZ_STALL_ON_OOM
// Implementation of VirtualAlloc wrapper (bug 1716727). // Implementation of VirtualAlloc wrapper (bug 1716727).
@ -1377,7 +1384,16 @@ constexpr size_t kMaxAttempts = 10;
// Microsoft's documentation for ::Sleep() for details.) // Microsoft's documentation for ::Sleep() for details.)
constexpr size_t kDelayMs = 50; constexpr size_t kDelayMs = 50;
// Drop-in wrapper around VirtualAlloc. When out of memory, attempts to stall Atomic<bool> sHasStalled{false};
static bool ShouldStallAndRetry() {
if (sShouldAlwaysStall) {
return true;
}
// Otherwise, stall at most once.
return sHasStalled.compareExchange(false, true);
}
// Drop-in wrapper around VirtualAlloc. When out of memory, may attempt to stall
// and retry rather than returning immediately, in hopes that the page file is // and retry rather than returning immediately, in hopes that the page file is
// about to be expanded by Windows. // about to be expanded by Windows.
// //
@ -1409,8 +1425,11 @@ constexpr size_t kDelayMs = 50;
if (!(flAllocationType & MEM_COMMIT)) return nullptr; if (!(flAllocationType & MEM_COMMIT)) return nullptr;
} }
// Unconditionally retry. (At this level, we don't know whether the allocation // Also return if we just aren't supposed to be retrying at the moment, for
// is fallible, and arguably we should retry even if we knew that it was.) // whatever reason.
if (!ShouldStallAndRetry()) return nullptr;
// Otherwise, retry.
for (size_t i = 0; i < kMaxAttempts; ++i) { for (size_t i = 0; i < kMaxAttempts; ++i) {
::Sleep(kDelayMs); ::Sleep(kDelayMs);
void* ptr = ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); void* ptr = ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);

View File

@ -24,6 +24,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Types.h" #include "mozilla/Types.h"
#include "mozjemalloc_types.h" #include "mozjemalloc_types.h"
#include "stdbool.h"
#ifdef MOZ_MEMORY #ifdef MOZ_MEMORY
// On OSX, malloc/malloc.h contains the declaration for malloc_good_size, // On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
@ -60,6 +61,13 @@ static inline void jemalloc_stats(jemalloc_stats_t* aStats) {
} }
# endif # endif
// Temporary configurator for experiment associated with bug 1716727.
# if defined(XP_WIN)
MOZ_JEMALLOC_API void mozjemalloc_experiment_set_always_stall(bool);
# else
static inline void mozjemalloc_experiment_set_always_stall(bool){};
# endif
#endif // MOZ_MEMORY #endif // MOZ_MEMORY
#define NOTHROW_MALLOC_DECL(name, return_type, ...) \ #define NOTHROW_MALLOC_DECL(name, return_type, ...) \

View File

@ -5,6 +5,7 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "mozmemory.h"
#include <stdlib.h> #include <stdlib.h>
#if defined(MOZ_WIDGET_GTK) #if defined(MOZ_WIDGET_GTK)
@ -274,14 +275,25 @@ void XRE_SetProcessType(const char* aProcessTypeString) {
} }
called = true; called = true;
sChildProcessType = GeckoProcessType_Invalid; sChildProcessType = [&] {
for (GeckoProcessType t : for (GeckoProcessType t :
MakeEnumeratedRange(GeckoProcessType::GeckoProcessType_End)) { MakeEnumeratedRange(GeckoProcessType::GeckoProcessType_End)) {
if (!strcmp(XRE_GeckoProcessTypeToString(t), aProcessTypeString)) { if (!strcmp(XRE_GeckoProcessTypeToString(t), aProcessTypeString)) {
sChildProcessType = t; return t;
return; }
} }
} return GeckoProcessType_Invalid;
}();
#ifdef MOZ_MEMORY
// For the parent process, we're probably willing to accept an apparent
// lockup in preference to a crash. Always stall and retry.
//
// For child processes, an obvious OOM-crash may be preferable to slow
// performance. Retry at most once per process, then give up.
mozjemalloc_experiment_set_always_stall(sChildProcessType ==
GeckoProcessType_Default);
#endif
} }
#if defined(XP_WIN) #if defined(XP_WIN)