2017-01-11 10:06:31 +08:00
|
|
|
#ifndef JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H
|
|
|
|
#define JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H
|
2017-04-11 08:11:33 +08:00
|
|
|
|
2017-11-05 03:50:19 +08:00
|
|
|
#include "jemalloc/internal/arena_stats.h"
|
2017-04-11 10:04:40 +08:00
|
|
|
#include "jemalloc/internal/atomic.h"
|
2017-10-02 08:22:06 +08:00
|
|
|
#include "jemalloc/internal/bin.h"
|
2017-04-21 05:32:24 +08:00
|
|
|
#include "jemalloc/internal/bitmap.h"
|
2019-09-21 10:59:55 +08:00
|
|
|
#include "jemalloc/internal/eset.h"
|
2017-05-24 05:36:09 +08:00
|
|
|
#include "jemalloc/internal/extent_dss.h"
|
2017-04-20 06:09:01 +08:00
|
|
|
#include "jemalloc/internal/jemalloc_internal_types.h"
|
2017-05-24 03:28:19 +08:00
|
|
|
#include "jemalloc/internal/mutex.h"
|
2017-04-18 07:17:02 +08:00
|
|
|
#include "jemalloc/internal/nstime.h"
|
2017-04-11 08:11:33 +08:00
|
|
|
#include "jemalloc/internal/ql.h"
|
2017-12-15 04:46:39 +08:00
|
|
|
#include "jemalloc/internal/sc.h"
|
2017-04-20 06:15:57 +08:00
|
|
|
#include "jemalloc/internal/smoothstep.h"
|
2017-04-20 04:39:33 +08:00
|
|
|
#include "jemalloc/internal/ticker.h"
|
2017-04-11 08:11:33 +08:00
|
|
|
|
2017-01-11 10:06:31 +08:00
|
|
|
struct arena_decay_s {
|
2017-03-02 03:21:18 +08:00
|
|
|
/* Synchronizes all non-atomic fields. */
|
2017-02-14 03:02:32 +08:00
|
|
|
malloc_mutex_t mtx;
|
2017-03-08 11:52:57 +08:00
|
|
|
/*
|
|
|
|
* True if a thread is currently purging the extents associated with
|
|
|
|
* this decay structure.
|
|
|
|
*/
|
|
|
|
bool purging;
|
2017-01-11 10:06:31 +08:00
|
|
|
/*
|
2017-05-18 01:47:00 +08:00
|
|
|
* Approximate time in milliseconds from the creation of a set of unused
|
2017-01-11 10:06:31 +08:00
|
|
|
* dirty pages until an equivalent set of unused dirty pages is purged
|
|
|
|
* and/or reused.
|
|
|
|
*/
|
2017-05-18 01:47:00 +08:00
|
|
|
atomic_zd_t time_ms;
|
2017-01-11 10:06:31 +08:00
|
|
|
/* time / SMOOTHSTEP_NSTEPS. */
|
|
|
|
nstime_t interval;
|
|
|
|
/*
|
|
|
|
* Time at which the current decay interval logically started. We do
|
|
|
|
* not actually advance to a new epoch until sometime after it starts
|
|
|
|
* because of scheduling and computation delays, and it is even possible
|
|
|
|
* to completely skip epochs. In all cases, during epoch advancement we
|
|
|
|
* merge all relevant activity into the most recently recorded epoch.
|
|
|
|
*/
|
|
|
|
nstime_t epoch;
|
|
|
|
/* Deadline randomness generator. */
|
|
|
|
uint64_t jitter_state;
|
|
|
|
/*
|
|
|
|
* Deadline for current epoch. This is the sum of interval and per
|
|
|
|
* epoch jitter which is a uniform random variable in [0..interval).
|
|
|
|
* Epochs always advance by precise multiples of interval, but we
|
|
|
|
* randomize the deadline to reduce the likelihood of arenas purging in
|
|
|
|
* lockstep.
|
|
|
|
*/
|
|
|
|
nstime_t deadline;
|
|
|
|
/*
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
* Number of unpurged pages at beginning of current epoch. During epoch
|
|
|
|
* advancement we use the delta between arena->decay_*.nunpurged and
|
2019-09-21 11:52:13 +08:00
|
|
|
* eset_npages_get(&arena->extents_*) to determine how many dirty pages,
|
|
|
|
* if any, were generated.
|
2017-01-11 10:06:31 +08:00
|
|
|
*/
|
|
|
|
size_t nunpurged;
|
|
|
|
/*
|
|
|
|
* Trailing log of how many unused dirty pages were generated during
|
|
|
|
* each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last
|
|
|
|
* element is the most recent epoch. Corresponding epoch times are
|
|
|
|
* relative to epoch.
|
|
|
|
*/
|
|
|
|
size_t backlog[SMOOTHSTEP_NSTEPS];
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pointer to associated stats. These stats are embedded directly in
|
|
|
|
* the arena's stats due to how stats structures are shared between the
|
|
|
|
* arena and ctl code.
|
|
|
|
*
|
|
|
|
* Synchronization: Same as associated arena's stats field. */
|
2017-11-05 03:50:19 +08:00
|
|
|
arena_stats_decay_t *stats;
|
2017-05-23 04:09:17 +08:00
|
|
|
/* Peak number of pages in associated extents. Used for debug only. */
|
|
|
|
uint64_t ceil_npages;
|
2017-01-11 10:06:31 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct arena_s {
|
|
|
|
/*
|
2017-01-30 13:57:14 +08:00
|
|
|
* Number of threads currently assigned to this arena. Each thread has
|
|
|
|
* two distinct assignments, one for application-serving allocation, and
|
|
|
|
* the other for internal metadata allocation. Internal metadata must
|
|
|
|
* not be allocated from arenas explicitly created via the arenas.create
|
|
|
|
* mallctl, because the arena.<i>.reset mallctl indiscriminately
|
|
|
|
* discards all allocations for the affected arena.
|
2017-01-11 10:06:31 +08:00
|
|
|
*
|
|
|
|
* 0: Application allocation.
|
|
|
|
* 1: Internal metadata allocation.
|
2017-01-30 13:57:14 +08:00
|
|
|
*
|
|
|
|
* Synchronization: atomic.
|
2017-01-11 10:06:31 +08:00
|
|
|
*/
|
2017-04-05 08:22:24 +08:00
|
|
|
atomic_u_t nthreads[2];
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2018-11-13 07:56:04 +08:00
|
|
|
/* Next bin shard for binding new threads. Synchronization: atomic. */
|
|
|
|
atomic_u_t binshard_next;
|
|
|
|
|
Implement per-CPU arena.
The new feature, opt.percpu_arena, determines thread-arena association
dynamically based CPU id. Three modes are supported: "percpu", "phycpu"
and disabled.
"percpu" uses the current core id (with help from sched_getcpu())
directly as the arena index, while "phycpu" will assign threads on the
same physical CPU to the same arena. In other words, "percpu" means # of
arenas == # of CPUs, while "phycpu" has # of arenas == 1/2 * (# of
CPUs). Note that no runtime check on whether hyper threading is enabled
is added yet.
When enabled, threads will be migrated between arenas when a CPU change
is detected. In the current design, to reduce overhead from reading CPU
id, each arena tracks the thread accessed most recently. When a new
thread comes in, we will read CPU id and update arena if necessary.
2017-02-03 09:02:05 +08:00
|
|
|
/*
|
|
|
|
* When percpu_arena is enabled, to amortize the cost of reading /
|
|
|
|
* updating the current CPU id, track the most recent thread accessing
|
|
|
|
* this arena, and only read CPU if there is a mismatch.
|
|
|
|
*/
|
|
|
|
tsdn_t *last_thd;
|
|
|
|
|
2017-02-13 09:43:33 +08:00
|
|
|
/* Synchronization: internal. */
|
2017-01-11 10:06:31 +08:00
|
|
|
arena_stats_t stats;
|
2017-02-13 09:43:33 +08:00
|
|
|
|
2017-01-11 10:06:31 +08:00
|
|
|
/*
|
2017-08-12 08:34:21 +08:00
|
|
|
* Lists of tcaches and cache_bin_array_descriptors for extant threads
|
|
|
|
* associated with this arena. Stats from these are merged
|
|
|
|
* incrementally, and at exit if opt_stats_print is enabled.
|
2017-01-30 13:57:14 +08:00
|
|
|
*
|
2017-02-13 10:50:53 +08:00
|
|
|
* Synchronization: tcache_ql_mtx.
|
2017-01-11 10:06:31 +08:00
|
|
|
*/
|
2017-08-12 08:34:21 +08:00
|
|
|
ql_head(tcache_t) tcache_ql;
|
|
|
|
ql_head(cache_bin_array_descriptor_t) cache_bin_array_descriptor_ql;
|
|
|
|
malloc_mutex_t tcache_ql_mtx;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-02-13 09:03:46 +08:00
|
|
|
/* Synchronization: internal. */
|
|
|
|
prof_accum_t prof_accum;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
|
|
|
* Extent serial number generator state.
|
|
|
|
*
|
|
|
|
* Synchronization: atomic.
|
|
|
|
*/
|
2017-04-05 08:22:24 +08:00
|
|
|
atomic_zu_t extent_sn_next;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-04-05 08:22:24 +08:00
|
|
|
/*
|
|
|
|
* Represents a dss_prec_t, but atomically.
|
|
|
|
*
|
|
|
|
* Synchronization: atomic.
|
|
|
|
*/
|
|
|
|
atomic_u_t dss_prec;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
|
|
|
* Number of pages in active extents.
|
|
|
|
*
|
|
|
|
* Synchronization: atomic.
|
|
|
|
*/
|
2017-04-05 08:22:24 +08:00
|
|
|
atomic_zu_t nactive;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
|
|
|
* Extant large allocations.
|
|
|
|
*
|
|
|
|
* Synchronization: large_mtx.
|
|
|
|
*/
|
|
|
|
extent_list_t large;
|
2017-01-11 10:06:31 +08:00
|
|
|
/* Synchronizes all large allocation/update/deallocation. */
|
|
|
|
malloc_mutex_t large_mtx;
|
|
|
|
|
|
|
|
/*
|
2017-01-30 13:57:14 +08:00
|
|
|
* Collections of extents that were previously allocated. These are
|
|
|
|
* used when allocating extents, in an attempt to re-use address space.
|
|
|
|
*
|
|
|
|
* Synchronization: internal.
|
2017-01-11 10:06:31 +08:00
|
|
|
*/
|
2019-09-22 01:35:47 +08:00
|
|
|
eset_t eset_dirty;
|
|
|
|
eset_t eset_muzzy;
|
|
|
|
eset_t eset_retained;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-03-08 01:22:33 +08:00
|
|
|
/*
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
* Decay-based purging state, responsible for scheduling extent state
|
|
|
|
* transitions.
|
2017-03-08 01:22:33 +08:00
|
|
|
*
|
|
|
|
* Synchronization: internal.
|
|
|
|
*/
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
arena_decay_t decay_dirty; /* dirty --> muzzy */
|
|
|
|
arena_decay_t decay_muzzy; /* muzzy --> retained */
|
2017-03-08 01:22:33 +08:00
|
|
|
|
2017-01-11 10:06:31 +08:00
|
|
|
/*
|
|
|
|
* Next extent size class in a growing series to use when satisfying a
|
2017-04-27 07:26:12 +08:00
|
|
|
* request via the extent hooks (only if opt_retain). This limits the
|
2017-04-25 08:28:55 +08:00
|
|
|
* number of disjoint virtual memory ranges so that extent merging can
|
|
|
|
* be effective even if multiple arenas' extent allocation requests are
|
|
|
|
* highly interleaved.
|
2017-01-30 13:57:14 +08:00
|
|
|
*
|
2017-11-03 08:48:39 +08:00
|
|
|
* retain_grow_limit is the max allowed size ind to expand (unless the
|
|
|
|
* required size is greater). Default is no limit, and controlled
|
|
|
|
* through mallctl only.
|
|
|
|
*
|
2017-05-27 02:06:01 +08:00
|
|
|
* Synchronization: extent_grow_mtx
|
2017-01-11 10:06:31 +08:00
|
|
|
*/
|
2017-05-27 02:06:01 +08:00
|
|
|
pszind_t extent_grow_next;
|
2017-11-03 08:48:39 +08:00
|
|
|
pszind_t retain_grow_limit;
|
2017-05-27 02:06:01 +08:00
|
|
|
malloc_mutex_t extent_grow_mtx;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
2017-04-17 13:31:16 +08:00
|
|
|
* Available extent structures that were allocated via
|
|
|
|
* base_alloc_extent().
|
2017-01-30 13:57:14 +08:00
|
|
|
*
|
2017-04-17 13:31:16 +08:00
|
|
|
* Synchronization: extent_avail_mtx.
|
2017-01-30 13:57:14 +08:00
|
|
|
*/
|
2017-04-17 13:31:16 +08:00
|
|
|
extent_tree_t extent_avail;
|
2018-08-02 05:14:33 +08:00
|
|
|
atomic_zu_t extent_avail_cnt;
|
2017-04-17 13:31:16 +08:00
|
|
|
malloc_mutex_t extent_avail_mtx;
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
|
|
|
* bins is used to store heaps of free regions.
|
|
|
|
*
|
|
|
|
* Synchronization: internal.
|
|
|
|
*/
|
2018-11-13 07:56:04 +08:00
|
|
|
bins_t bins[SC_NBINS];
|
2017-01-11 10:06:31 +08:00
|
|
|
|
2017-01-30 13:57:14 +08:00
|
|
|
/*
|
|
|
|
* Base allocator, from which arena metadata are allocated.
|
|
|
|
*
|
|
|
|
* Synchronization: internal.
|
|
|
|
*/
|
2017-01-11 10:06:31 +08:00
|
|
|
base_t *base;
|
2017-05-17 04:56:00 +08:00
|
|
|
/* Used to determine uptime. Read-only after initialization. */
|
|
|
|
nstime_t create_time;
|
2017-01-11 10:06:31 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Used in conjunction with tsd for fast arena-related context lookup. */
|
|
|
|
struct arena_tdata_s {
|
|
|
|
ticker_t decay_ticker;
|
|
|
|
};
|
|
|
|
|
2017-04-12 09:13:10 +08:00
|
|
|
/* Used to pass rtree lookup context down the path. */
|
|
|
|
struct alloc_ctx_s {
|
2017-04-08 05:12:30 +08:00
|
|
|
szind_t szind;
|
|
|
|
bool slab;
|
|
|
|
};
|
|
|
|
|
2017-01-11 10:06:31 +08:00
|
|
|
#endif /* JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H */
|