Add arena.i.retain_grow_limit
This option controls the max size when grow_retained. This is useful when we have customized extent hooks reserving physical memory (e.g. 1G huge pages). Without this feature, the default increasing sequence could result in fragmented and wasted physical memory.
This commit is contained in:
28
src/arena.c
28
src/arena.c
@@ -1886,6 +1886,33 @@ arena_muzzy_decay_ms_default_set(ssize_t decay_ms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
arena_retain_grow_limit_get_set(tsd_t *tsd, arena_t *arena, size_t *old_limit,
|
||||
size_t *new_limit) {
|
||||
assert(opt_retain);
|
||||
|
||||
pszind_t new_ind JEMALLOC_CC_SILENCE_INIT(0);
|
||||
if (new_limit != NULL) {
|
||||
size_t limit = *new_limit;
|
||||
/* Grow no more than the new limit. */
|
||||
if ((new_ind = sz_psz2ind(limit + 1) - 1) >
|
||||
EXTENT_GROW_MAX_PIND) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &arena->extent_grow_mtx);
|
||||
if (old_limit != NULL) {
|
||||
*old_limit = sz_pind2sz(arena->retain_grow_limit);
|
||||
}
|
||||
if (new_limit != NULL) {
|
||||
arena->retain_grow_limit = new_ind;
|
||||
}
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &arena->extent_grow_mtx);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned
|
||||
arena_nthreads_get(arena_t *arena, bool internal) {
|
||||
return atomic_load_u(&arena->nthreads[internal], ATOMIC_RELAXED);
|
||||
@@ -2013,6 +2040,7 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
}
|
||||
|
||||
arena->extent_grow_next = sz_psz2ind(HUGEPAGE);
|
||||
arena->retain_grow_limit = EXTENT_GROW_MAX_PIND;
|
||||
if (malloc_mutex_init(&arena->extent_grow_mtx, "extent_grow",
|
||||
WITNESS_RANK_EXTENT_GROW, malloc_mutex_rank_exclusive)) {
|
||||
goto label_error;
|
||||
|
42
src/ctl.c
42
src/ctl.c
@@ -118,6 +118,7 @@ CTL_PROTO(arena_i_dss)
|
||||
CTL_PROTO(arena_i_dirty_decay_ms)
|
||||
CTL_PROTO(arena_i_muzzy_decay_ms)
|
||||
CTL_PROTO(arena_i_extent_hooks)
|
||||
CTL_PROTO(arena_i_retain_grow_limit)
|
||||
INDEX_PROTO(arena_i)
|
||||
CTL_PROTO(arenas_bin_i_size)
|
||||
CTL_PROTO(arenas_bin_i_nregs)
|
||||
@@ -320,7 +321,8 @@ static const ctl_named_node_t arena_i_node[] = {
|
||||
{NAME("dss"), CTL(arena_i_dss)},
|
||||
{NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)},
|
||||
{NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)},
|
||||
{NAME("extent_hooks"), CTL(arena_i_extent_hooks)}
|
||||
{NAME("extent_hooks"), CTL(arena_i_extent_hooks)},
|
||||
{NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)}
|
||||
};
|
||||
static const ctl_named_node_t super_arena_i_node[] = {
|
||||
{NAME(""), CHILD(named, arena_i)}
|
||||
@@ -2199,6 +2201,42 @@ label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
arena_i_retain_grow_limit_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned arena_ind;
|
||||
arena_t *arena;
|
||||
|
||||
if (!opt_retain) {
|
||||
/* Only relevant when retain is enabled. */
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
MIB_UNSIGNED(arena_ind, 1);
|
||||
if (arena_ind < narenas_total_get() && (arena =
|
||||
arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
|
||||
size_t old_limit, new_limit;
|
||||
if (newp != NULL) {
|
||||
WRITE(new_limit, size_t);
|
||||
}
|
||||
bool err = arena_retain_grow_limit_get_set(tsd, arena,
|
||||
&old_limit, newp != NULL ? &new_limit : NULL);
|
||||
if (!err) {
|
||||
READ(old_limit, size_t);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = EFAULT;
|
||||
}
|
||||
} else {
|
||||
ret = EFAULT;
|
||||
}
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const ctl_named_node_t *
|
||||
arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) {
|
||||
const ctl_named_node_t *ret;
|
||||
@@ -2260,7 +2298,7 @@ arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp)
|
||||
if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp)
|
||||
: arena_muzzy_decay_ms_default_set(*(ssize_t *)newp)) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
|
@@ -1284,13 +1284,14 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena,
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment extent_grow_next if doing so wouldn't exceed the legal
|
||||
* Increment extent_grow_next if doing so wouldn't exceed the allowed
|
||||
* range.
|
||||
*/
|
||||
if (arena->extent_grow_next + egn_skip + 1 < NPSIZES) {
|
||||
if (arena->extent_grow_next + egn_skip + 1 <=
|
||||
arena->retain_grow_limit) {
|
||||
arena->extent_grow_next += egn_skip + 1;
|
||||
} else {
|
||||
arena->extent_grow_next = NPSIZES - 1;
|
||||
arena->extent_grow_next = arena->retain_grow_limit;
|
||||
}
|
||||
/* All opportunities for failure are past. */
|
||||
malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx);
|
||||
|
Reference in New Issue
Block a user