Bug 1815069 - Make it possible to tweak mozjemalloc's max dirty page sizes dynamically, r=glandium,pbone

Differential Revision: https://phabricator.services.mozilla.com/D168900
This commit is contained in:
Olli Pettay 2023-03-02 09:15:57 +00:00
parent 94b151e6ac
commit c1c5ec3417
6 changed files with 64 additions and 2 deletions

View File

@ -121,6 +121,12 @@ MALLOC_DECL(moz_create_arena_with_params, arena_id_t, arena_params_t*)
// Passing an invalid id (inexistent or already disposed) to this function
// will crash. The arena must be empty prior to calling this function.
MALLOC_DECL(moz_dispose_arena, void, arena_id_t)
// Set the default modifier for mMaxDirty. The value is the number of shifts
// applied to the value. Positive value is handled as <<, negative >>.
// Arenas may override the default modifier.
MALLOC_DECL(moz_set_max_dirty_page_modifier, void, int32_t)
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_ALLOC

View File

@ -1138,6 +1138,9 @@ struct arena_t {
// Maximum value allowed for mNumDirty.
size_t mMaxDirty;
int32_t mMaxDirtyIncreaseOverride;
int32_t mMaxDirtyDecreaseOverride;
private:
// Size/address-ordered tree of this arena's available runs. This tree
// is used for first-best-fit run allocation.
@ -1290,6 +1293,11 @@ class ArenaCollection {
delete aArena;
}
void SetDefaultMaxDirtyPageModifier(int32_t aModifier) {
mDefaultMaxDirtyPageModifier = aModifier;
}
int32_t DefaultMaxDirtyPageModifier() { return mDefaultMaxDirtyPageModifier; }
using Tree = RedBlackTree<arena_t, ArenaTreeTrait>;
struct Iterator : Tree::Iterator {
@ -1328,6 +1336,7 @@ class ArenaCollection {
arena_id_t mLastPublicArenaId;
Tree mArenas;
Tree mPrivateArenas;
Atomic<int32_t> mDefaultMaxDirtyPageModifier;
};
static ArenaCollection gArenas;
@ -2760,8 +2769,20 @@ arena_run_t* arena_t::AllocRun(size_t aSize, bool aLarge, bool aZero) {
void arena_t::Purge(bool aAll) {
arena_chunk_t* chunk;
size_t i, npages;
int32_t modifier = gArenas.DefaultMaxDirtyPageModifier();
if (modifier) {
int32_t arenaOverride =
modifier > 0 ? mMaxDirtyIncreaseOverride : mMaxDirtyDecreaseOverride;
if (arenaOverride) {
modifier = arenaOverride;
}
}
// If all is set purge all dirty pages.
size_t dirty_max = aAll ? 1 : mMaxDirty;
size_t dirty_max = aAll ? 1
: modifier >= 0 ? mMaxDirty << modifier
: mMaxDirty >> -modifier;
#ifdef MOZ_DEBUG
size_t ndirty = 0;
for (auto chunk : mChunksDirty.iter()) {
@ -3884,7 +3905,14 @@ arena_t::arena_t(arena_params_t* aParams, bool aIsPrivate) {
default:
break;
}
mMaxDirtyIncreaseOverride = aParams->mMaxDirtyIncreaseOverride;
mMaxDirtyDecreaseOverride = aParams->mMaxDirtyDecreaseOverride;
} else {
mMaxDirtyIncreaseOverride = 0;
mMaxDirtyDecreaseOverride = 0;
}
mPRNG = nullptr;
mIsPrivate = aIsPrivate;
@ -4837,6 +4865,11 @@ inline void MozJemalloc::moz_dispose_arena(arena_id_t aArenaId) {
gArenas.DisposeArena(arena);
}
template <>
inline void MozJemalloc::moz_set_max_dirty_page_modifier(int32_t aModifier) {
gArenas.SetDefaultMaxDirtyPageModifier(aModifier);
}
#define MALLOC_DECL(name, return_type, ...) \
template <> \
inline return_type MozJemalloc::moz_arena_##name( \

View File

@ -65,6 +65,8 @@ struct DummyArenaAllocator {
static void moz_dispose_arena(arena_id_t) {}
static void moz_set_max_dirty_page_modifier(int32_t) {}
#define MALLOC_DECL(name, return_type, ...) \
static return_type moz_arena_##name( \
arena_id_t, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) { \

View File

@ -65,10 +65,22 @@ typedef size_t arena_id_t;
typedef struct arena_params_s {
size_t mMaxDirty;
// Arena specific modifiers which override the value passed to
// moz_set_max_dirty_page_modifier. If value > 0 is passed to that function,
// and mMaxDirtyIncreaseOverride != 0, mMaxDirtyIncreaseOverride will be used
// instead, and similarly if value < 0 is passed and mMaxDirtyDecreaseOverride
// != 0, mMaxDirtyDecreaseOverride will be used as the modifier.
int32_t mMaxDirtyIncreaseOverride;
int32_t mMaxDirtyDecreaseOverride;
uint32_t mFlags;
#ifdef __cplusplus
arena_params_s() : mMaxDirty(0), mFlags(0) {}
arena_params_s()
: mMaxDirty(0),
mMaxDirtyIncreaseOverride(0),
mMaxDirtyDecreaseOverride(0),
mFlags(0) {}
#endif
} arena_params_t;

View File

@ -1454,6 +1454,11 @@ void replace_moz_dispose_arena(arena_id_t aArenaId) {
return sMallocTable.moz_dispose_arena(aArenaId);
}
void replace_moz_set_max_dirty_page_modifier(int32_t aModifier) {
// No need to do anything special here.
return sMallocTable.moz_set_max_dirty_page_modifier(aModifier);
}
void* replace_moz_arena_malloc(arena_id_t aArenaId, size_t aReqSize) {
return PageMalloc(Some(aArenaId), aReqSize);
}

View File

@ -550,6 +550,10 @@ static void replace_moz_dispose_arena(arena_id_t aArenaId) {
return gMallocTable.moz_dispose_arena(aArenaId);
}
static void replace_moz_set_max_dirty_page_modifier(int32_t aModifier) {
return gMallocTable.moz_set_max_dirty_page_modifier(aModifier);
}
// Must come after all the replace_* funcs
void replace_init(malloc_table_t* aMallocTable, ReplaceMallocBridge** aBridge) {
gMallocTable = *aMallocTable;