mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-08-25 16:43:33 +03:00
Implement decay-based unused dirty page purging.
This is an alternative to the existing ratio-based unused dirty page purging, and is intended to eventually become the sole purging mechanism. Add mallctls: - opt.purge - opt.decay_time - arena.<i>.decay - arena.<i>.decay_time - arenas.decay_time - stats.arenas.<i>.decay_time This resolves #325.
This commit is contained in:
parent
8e82af1166
commit
243f7a0508
18 changed files with 1268 additions and 112 deletions
327
src/arena.c
327
src/arena.c
|
|
@ -4,8 +4,17 @@
|
|||
/******************************************************************************/
|
||||
/* Data. */
|
||||
|
||||
purge_mode_t opt_purge = PURGE_DEFAULT;
|
||||
const char *purge_mode_names[] = {
|
||||
"ratio",
|
||||
"decay",
|
||||
"N/A"
|
||||
};
|
||||
ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
|
||||
static ssize_t lg_dirty_mult_default;
|
||||
ssize_t opt_decay_time = DECAY_TIME_DEFAULT;
|
||||
static ssize_t decay_time_default;
|
||||
|
||||
arena_bin_info_t arena_bin_info[NBINS];
|
||||
|
||||
size_t map_bias;
|
||||
|
|
@ -1205,10 +1214,193 @@ arena_lg_dirty_mult_set(arena_t *arena, ssize_t lg_dirty_mult)
|
|||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
arena_decay_deadline_init(arena_t *arena)
|
||||
{
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
|
||||
/*
|
||||
* Generate a new deadline that is uniformly random within the next
|
||||
* epoch after the current one.
|
||||
*/
|
||||
time_copy(&arena->decay_deadline, &arena->decay_epoch);
|
||||
time_add(&arena->decay_deadline, &arena->decay_interval);
|
||||
if (arena->decay_time > 0) {
|
||||
uint64_t decay_interval_ns, r;
|
||||
struct timespec jitter;
|
||||
|
||||
decay_interval_ns = time_sec(&arena->decay_interval) *
|
||||
1000000000 + time_nsec(&arena->decay_interval);
|
||||
r = prng_range(&arena->decay_jitter_state, decay_interval_ns);
|
||||
time_init(&jitter, r / 1000000000, r % 1000000000);
|
||||
time_add(&arena->decay_deadline, &jitter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
arena_decay_deadline_reached(const arena_t *arena, const struct timespec *time)
|
||||
{
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
|
||||
return (time_compare(&arena->decay_deadline, time) <= 0);
|
||||
}
|
||||
|
||||
static size_t
|
||||
arena_decay_backlog_npages_limit(const arena_t *arena)
|
||||
{
|
||||
static const uint64_t h_steps[] = {
|
||||
#define STEP(step, h, x, y) \
|
||||
h,
|
||||
SMOOTHSTEP
|
||||
#undef STEP
|
||||
};
|
||||
uint64_t sum;
|
||||
size_t npages_limit_backlog;
|
||||
unsigned i;
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
|
||||
/*
|
||||
* For each element of decay_backlog, multiply by the corresponding
|
||||
* fixed-point smoothstep decay factor. Sum the products, then divide
|
||||
* to round down to the nearest whole number of pages.
|
||||
*/
|
||||
sum = 0;
|
||||
for (i = 0; i < SMOOTHSTEP_NSTEPS; i++)
|
||||
sum += arena->decay_backlog[i] * h_steps[i];
|
||||
npages_limit_backlog = (sum >> SMOOTHSTEP_BFP);
|
||||
|
||||
return (npages_limit_backlog);
|
||||
}
|
||||
|
||||
static void
|
||||
arena_decay_epoch_advance(arena_t *arena, const struct timespec *time)
|
||||
{
|
||||
uint64_t nadvance;
|
||||
struct timespec delta;
|
||||
size_t ndirty_delta;
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
assert(arena_decay_deadline_reached(arena, time));
|
||||
|
||||
time_copy(&delta, time);
|
||||
time_subtract(&delta, &arena->decay_epoch);
|
||||
nadvance = time_divide(&delta, &arena->decay_interval);
|
||||
assert(nadvance > 0);
|
||||
|
||||
/* Add nadvance decay intervals to epoch. */
|
||||
time_copy(&delta, &arena->decay_interval);
|
||||
time_imultiply(&delta, nadvance);
|
||||
time_add(&arena->decay_epoch, &delta);
|
||||
|
||||
/* Set a new deadline. */
|
||||
arena_decay_deadline_init(arena);
|
||||
|
||||
/* Update the backlog. */
|
||||
if (nadvance >= SMOOTHSTEP_NSTEPS) {
|
||||
memset(arena->decay_backlog, 0, (SMOOTHSTEP_NSTEPS-1) *
|
||||
sizeof(size_t));
|
||||
} else {
|
||||
memmove(arena->decay_backlog, &arena->decay_backlog[nadvance],
|
||||
(SMOOTHSTEP_NSTEPS - nadvance) * sizeof(size_t));
|
||||
if (nadvance > 1) {
|
||||
memset(&arena->decay_backlog[SMOOTHSTEP_NSTEPS -
|
||||
nadvance], 0, (nadvance-1) * sizeof(size_t));
|
||||
}
|
||||
}
|
||||
ndirty_delta = (arena->ndirty > arena->decay_ndirty) ? arena->ndirty -
|
||||
arena->decay_ndirty : 0;
|
||||
arena->decay_ndirty = arena->ndirty;
|
||||
arena->decay_backlog[SMOOTHSTEP_NSTEPS-1] = ndirty_delta;
|
||||
arena->decay_backlog_npages_limit =
|
||||
arena_decay_backlog_npages_limit(arena);
|
||||
}
|
||||
|
||||
static size_t
|
||||
arena_decay_npages_limit(arena_t *arena)
|
||||
{
|
||||
size_t npages_limit;
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
|
||||
npages_limit = arena->decay_backlog_npages_limit;
|
||||
|
||||
/* Add in any dirty pages created during the current epoch. */
|
||||
if (arena->ndirty > arena->decay_ndirty)
|
||||
npages_limit += arena->ndirty - arena->decay_ndirty;
|
||||
|
||||
return (npages_limit);
|
||||
}
|
||||
|
||||
static void
|
||||
arena_decay_init(arena_t *arena, ssize_t decay_time)
|
||||
{
|
||||
|
||||
arena->decay_time = decay_time;
|
||||
if (decay_time > 0) {
|
||||
time_init(&arena->decay_interval, decay_time, 0);
|
||||
time_idivide(&arena->decay_interval, SMOOTHSTEP_NSTEPS);
|
||||
}
|
||||
|
||||
time_init(&arena->decay_epoch, 0, 0);
|
||||
time_update(&arena->decay_epoch);
|
||||
arena->decay_jitter_state = (uint64_t)(uintptr_t)arena;
|
||||
arena_decay_deadline_init(arena);
|
||||
arena->decay_ndirty = arena->ndirty;
|
||||
arena->decay_backlog_npages_limit = 0;
|
||||
memset(arena->decay_backlog, 0, SMOOTHSTEP_NSTEPS * sizeof(size_t));
|
||||
}
|
||||
|
||||
static bool
|
||||
arena_decay_time_valid(ssize_t decay_time)
|
||||
{
|
||||
|
||||
return (decay_time >= -1 && decay_time <= TIME_SEC_MAX);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
arena_decay_time_get(arena_t *arena)
|
||||
{
|
||||
ssize_t decay_time;
|
||||
|
||||
malloc_mutex_lock(&arena->lock);
|
||||
decay_time = arena->decay_time;
|
||||
malloc_mutex_unlock(&arena->lock);
|
||||
|
||||
return (decay_time);
|
||||
}
|
||||
|
||||
bool
|
||||
arena_decay_time_set(arena_t *arena, ssize_t decay_time)
|
||||
{
|
||||
|
||||
if (!arena_decay_time_valid(decay_time))
|
||||
return (true);
|
||||
|
||||
malloc_mutex_lock(&arena->lock);
|
||||
/*
|
||||
* Restart decay backlog from scratch, which may cause many dirty pages
|
||||
* to be immediately purged. It would conceptually be possible to map
|
||||
* the old backlog onto the new backlog, but there is no justification
|
||||
* for such complexity since decay_time changes are intended to be
|
||||
* infrequent, either between the {-1, 0, >0} states, or a one-time
|
||||
* arbitrary change during initial arena configuration.
|
||||
*/
|
||||
arena_decay_init(arena, decay_time);
|
||||
arena_maybe_purge(arena);
|
||||
malloc_mutex_unlock(&arena->lock);
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
arena_maybe_purge_ratio(arena_t *arena)
|
||||
{
|
||||
|
||||
assert(opt_purge == purge_mode_ratio);
|
||||
|
||||
/* Don't purge if the option is disabled. */
|
||||
if (arena->lg_dirty_mult < 0)
|
||||
return;
|
||||
|
|
@ -1231,6 +1423,41 @@ arena_maybe_purge_ratio(arena_t *arena)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arena_maybe_purge_decay(arena_t *arena)
|
||||
{
|
||||
struct timespec time;
|
||||
size_t ndirty_limit;
|
||||
|
||||
assert(opt_purge == purge_mode_decay);
|
||||
|
||||
/* Purge all or nothing if the option is disabled. */
|
||||
if (arena->decay_time <= 0) {
|
||||
if (arena->decay_time == 0)
|
||||
arena_purge_to_limit(arena, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
time_copy(&time, &arena->decay_epoch);
|
||||
if (unlikely(time_update(&time))) {
|
||||
/* Time went backwards. Force an epoch advance. */
|
||||
time_copy(&time, &arena->decay_deadline);
|
||||
}
|
||||
|
||||
if (arena_decay_deadline_reached(arena, &time))
|
||||
arena_decay_epoch_advance(arena, &time);
|
||||
|
||||
ndirty_limit = arena_decay_npages_limit(arena);
|
||||
|
||||
/*
|
||||
* Don't try to purge unless the number of purgeable pages exceeds the
|
||||
* current limit.
|
||||
*/
|
||||
if (arena->ndirty <= ndirty_limit)
|
||||
return;
|
||||
arena_purge_to_limit(arena, ndirty_limit);
|
||||
}
|
||||
|
||||
void
|
||||
arena_maybe_purge(arena_t *arena)
|
||||
{
|
||||
|
|
@ -1239,7 +1466,10 @@ arena_maybe_purge(arena_t *arena)
|
|||
if (arena->purging)
|
||||
return;
|
||||
|
||||
arena_maybe_purge_ratio(arena);
|
||||
if (opt_purge == purge_mode_ratio)
|
||||
arena_maybe_purge_ratio(arena);
|
||||
else
|
||||
arena_maybe_purge_decay(arena);
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
|
@ -1298,6 +1528,9 @@ arena_stash_dirty(arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||
UNUSED void *chunk;
|
||||
|
||||
npages = extent_node_size_get(chunkselm) >> LG_PAGE;
|
||||
if (opt_purge == purge_mode_decay && arena->ndirty -
|
||||
(nstashed + npages) < ndirty_limit)
|
||||
break;
|
||||
|
||||
chunkselm_next = qr_next(chunkselm, cc_link);
|
||||
/*
|
||||
|
|
@ -1327,6 +1560,9 @@ arena_stash_dirty(arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||
arena_mapbits_unallocated_size_get(chunk, pageind);
|
||||
|
||||
npages = run_size >> LG_PAGE;
|
||||
if (opt_purge == purge_mode_decay && arena->ndirty -
|
||||
(nstashed + npages) < ndirty_limit)
|
||||
break;
|
||||
|
||||
assert(pageind + npages <= chunk_npages);
|
||||
assert(arena_mapbits_dirty_get(chunk, pageind) ==
|
||||
|
|
@ -1352,7 +1588,8 @@ arena_stash_dirty(arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||
}
|
||||
|
||||
nstashed += npages;
|
||||
if (arena->ndirty - nstashed <= ndirty_limit)
|
||||
if (opt_purge == purge_mode_ratio && arena->ndirty - nstashed <=
|
||||
ndirty_limit)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1492,6 +1729,15 @@ arena_unstash_purged(arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: ndirty_limit is interpreted differently depending on opt_purge:
|
||||
* - purge_mode_ratio: Purge as few dirty run/chunks as possible to reach the
|
||||
* desired state:
|
||||
* (arena->ndirty <= ndirty_limit)
|
||||
* - purge_mode_decay: Purge as many dirty runs/chunks as possible without
|
||||
* violating the invariant:
|
||||
* (arena->ndirty >= ndirty_limit)
|
||||
*/
|
||||
static void
|
||||
arena_purge_to_limit(arena_t *arena, size_t ndirty_limit)
|
||||
{
|
||||
|
|
@ -1510,8 +1756,8 @@ arena_purge_to_limit(arena_t *arena, size_t ndirty_limit)
|
|||
size_t ndirty = arena_dirty_count(arena);
|
||||
assert(ndirty == arena->ndirty);
|
||||
}
|
||||
assert((arena->nactive >> arena->lg_dirty_mult) < arena->ndirty ||
|
||||
ndirty_limit == 0);
|
||||
assert(opt_purge != purge_mode_ratio || (arena->nactive >>
|
||||
arena->lg_dirty_mult) < arena->ndirty || ndirty_limit == 0);
|
||||
|
||||
qr_new(&purge_runs_sentinel, rd_link);
|
||||
extent_node_dirty_linkage_init(&purge_chunks_sentinel);
|
||||
|
|
@ -1534,11 +1780,14 @@ label_return:
|
|||
}
|
||||
|
||||
void
|
||||
arena_purge_all(arena_t *arena)
|
||||
arena_purge(arena_t *arena, bool all)
|
||||
{
|
||||
|
||||
malloc_mutex_lock(&arena->lock);
|
||||
arena_purge_to_limit(arena, 0);
|
||||
if (all)
|
||||
arena_purge_to_limit(arena, 0);
|
||||
else
|
||||
arena_maybe_purge(arena);
|
||||
malloc_mutex_unlock(&arena->lock);
|
||||
}
|
||||
|
||||
|
|
@ -1960,8 +2209,8 @@ arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
|
|||
}
|
||||
|
||||
void
|
||||
arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, szind_t binind,
|
||||
uint64_t prof_accumbytes)
|
||||
arena_tcache_fill_small(tsd_t *tsd, arena_t *arena, tcache_bin_t *tbin,
|
||||
szind_t binind, uint64_t prof_accumbytes)
|
||||
{
|
||||
unsigned i, nfill;
|
||||
arena_bin_t *bin;
|
||||
|
|
@ -2008,6 +2257,7 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, szind_t binind,
|
|||
}
|
||||
malloc_mutex_unlock(&bin->lock);
|
||||
tbin->ncached = i;
|
||||
arena_decay_tick(tsd, arena);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2118,7 +2368,8 @@ arena_quarantine_junk_small(void *ptr, size_t usize)
|
|||
}
|
||||
|
||||
static void *
|
||||
arena_malloc_small(arena_t *arena, size_t size, szind_t binind, bool zero)
|
||||
arena_malloc_small(tsd_t *tsd, arena_t *arena, size_t size, szind_t binind,
|
||||
bool zero)
|
||||
{
|
||||
void *ret;
|
||||
arena_bin_t *bin;
|
||||
|
|
@ -2166,11 +2417,13 @@ arena_malloc_small(arena_t *arena, size_t size, szind_t binind, bool zero)
|
|||
memset(ret, 0, size);
|
||||
}
|
||||
|
||||
arena_decay_tick(tsd, arena);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void *
|
||||
arena_malloc_large(arena_t *arena, size_t size, szind_t binind, bool zero)
|
||||
arena_malloc_large(tsd_t *tsd, arena_t *arena, size_t size, szind_t binind,
|
||||
bool zero)
|
||||
{
|
||||
void *ret;
|
||||
size_t usize;
|
||||
|
|
@ -2227,6 +2480,7 @@ arena_malloc_large(arena_t *arena, size_t size, szind_t binind, bool zero)
|
|||
}
|
||||
}
|
||||
|
||||
arena_decay_tick(tsd, arena);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
|
@ -2240,9 +2494,9 @@ arena_malloc_hard(tsd_t *tsd, arena_t *arena, size_t size, szind_t ind,
|
|||
return (NULL);
|
||||
|
||||
if (likely(size <= SMALL_MAXCLASS))
|
||||
return (arena_malloc_small(arena, size, ind, zero));
|
||||
return (arena_malloc_small(tsd, arena, size, ind, zero));
|
||||
if (likely(size <= large_maxclass))
|
||||
return (arena_malloc_large(arena, size, ind, zero));
|
||||
return (arena_malloc_large(tsd, arena, size, ind, zero));
|
||||
return (huge_malloc(tsd, arena, size, zero, tcache));
|
||||
}
|
||||
|
||||
|
|
@ -2329,6 +2583,7 @@ arena_palloc_large(tsd_t *tsd, arena_t *arena, size_t usize, size_t alignment,
|
|||
else if (unlikely(opt_zero))
|
||||
memset(ret, 0, usize);
|
||||
}
|
||||
arena_decay_tick(tsd, arena);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
|
@ -2515,7 +2770,7 @@ arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
|
|||
}
|
||||
|
||||
void
|
||||
arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
|
||||
arena_dalloc_small(tsd_t *tsd, arena_t *arena, arena_chunk_t *chunk, void *ptr,
|
||||
size_t pageind)
|
||||
{
|
||||
arena_chunk_map_bits_t *bitselm;
|
||||
|
|
@ -2527,6 +2782,7 @@ arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
|
|||
}
|
||||
bitselm = arena_bitselm_get(chunk, pageind);
|
||||
arena_dalloc_bin(arena, chunk, ptr, pageind, bitselm);
|
||||
arena_decay_tick(tsd, arena);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_JET
|
||||
|
|
@ -2583,12 +2839,13 @@ arena_dalloc_large_junked_locked(arena_t *arena, arena_chunk_t *chunk,
|
|||
}
|
||||
|
||||
void
|
||||
arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
|
||||
arena_dalloc_large(tsd_t *tsd, arena_t *arena, arena_chunk_t *chunk, void *ptr)
|
||||
{
|
||||
|
||||
malloc_mutex_lock(&arena->lock);
|
||||
arena_dalloc_large_locked_impl(arena, chunk, ptr, false);
|
||||
malloc_mutex_unlock(&arena->lock);
|
||||
arena_decay_tick(tsd, arena);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2789,14 +3046,16 @@ arena_ralloc_large(void *ptr, size_t oldsize, size_t usize_min,
|
|||
}
|
||||
|
||||
bool
|
||||
arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
bool zero)
|
||||
arena_ralloc_no_move(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,
|
||||
size_t extra, bool zero)
|
||||
{
|
||||
size_t usize_min, usize_max;
|
||||
|
||||
usize_min = s2u(size);
|
||||
usize_max = s2u(size + extra);
|
||||
if (likely(oldsize <= large_maxclass && usize_min <= large_maxclass)) {
|
||||
arena_chunk_t *chunk;
|
||||
|
||||
/*
|
||||
* Avoid moving the allocation if the size class can be left the
|
||||
* same.
|
||||
|
|
@ -2816,10 +3075,12 @@ arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,
|
|||
return (true);
|
||||
}
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
arena_decay_tick(tsd, extent_node_arena_get(&chunk->node));
|
||||
return (false);
|
||||
} else {
|
||||
return (huge_ralloc_no_move(ptr, oldsize, usize_min, usize_max,
|
||||
zero));
|
||||
return (huge_ralloc_no_move(tsd, ptr, oldsize, usize_min,
|
||||
usize_max, zero));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2852,7 +3113,7 @@ arena_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize, size_t size,
|
|||
size_t copysize;
|
||||
|
||||
/* Try to avoid moving the allocation. */
|
||||
if (!arena_ralloc_no_move(ptr, oldsize, usize, 0, zero))
|
||||
if (!arena_ralloc_no_move(tsd, ptr, oldsize, usize, 0, zero))
|
||||
return (ptr);
|
||||
|
||||
/*
|
||||
|
|
@ -2915,15 +3176,36 @@ bool
|
|||
arena_lg_dirty_mult_default_set(ssize_t lg_dirty_mult)
|
||||
{
|
||||
|
||||
if (opt_purge != purge_mode_ratio)
|
||||
return (true);
|
||||
if (!arena_lg_dirty_mult_valid(lg_dirty_mult))
|
||||
return (true);
|
||||
atomic_write_z((size_t *)&lg_dirty_mult_default, (size_t)lg_dirty_mult);
|
||||
return (false);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
arena_decay_time_default_get(void)
|
||||
{
|
||||
|
||||
return ((ssize_t)atomic_read_z((size_t *)&decay_time_default));
|
||||
}
|
||||
|
||||
bool
|
||||
arena_decay_time_default_set(ssize_t decay_time)
|
||||
{
|
||||
|
||||
if (opt_purge != purge_mode_decay)
|
||||
return (true);
|
||||
if (!arena_decay_time_valid(decay_time))
|
||||
return (true);
|
||||
atomic_write_z((size_t *)&decay_time_default, (size_t)decay_time);
|
||||
return (false);
|
||||
}
|
||||
|
||||
void
|
||||
arena_stats_merge(arena_t *arena, const char **dss, ssize_t *lg_dirty_mult,
|
||||
size_t *nactive, size_t *ndirty, arena_stats_t *astats,
|
||||
ssize_t *decay_time, size_t *nactive, size_t *ndirty, arena_stats_t *astats,
|
||||
malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats,
|
||||
malloc_huge_stats_t *hstats)
|
||||
{
|
||||
|
|
@ -2932,6 +3214,7 @@ arena_stats_merge(arena_t *arena, const char **dss, ssize_t *lg_dirty_mult,
|
|||
malloc_mutex_lock(&arena->lock);
|
||||
*dss = dss_prec_names[arena->dss_prec];
|
||||
*lg_dirty_mult = arena->lg_dirty_mult;
|
||||
*decay_time = arena->decay_time;
|
||||
*nactive += arena->nactive;
|
||||
*ndirty += arena->ndirty;
|
||||
|
||||
|
|
@ -3050,6 +3333,9 @@ arena_new(unsigned ind)
|
|||
qr_new(&arena->runs_dirty, rd_link);
|
||||
qr_new(&arena->chunks_cache, cc_link);
|
||||
|
||||
if (opt_purge == purge_mode_decay)
|
||||
arena_decay_init(arena, arena_decay_time_default_get());
|
||||
|
||||
ql_new(&arena->huge);
|
||||
if (malloc_mutex_init(&arena->huge_mtx))
|
||||
return (NULL);
|
||||
|
|
@ -3227,6 +3513,7 @@ arena_boot(void)
|
|||
unsigned i;
|
||||
|
||||
arena_lg_dirty_mult_default_set(opt_lg_dirty_mult);
|
||||
arena_decay_time_default_set(opt_decay_time);
|
||||
|
||||
/*
|
||||
* Compute the header size such that it is large enough to contain the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue