Add extents information to mallocstats output
- Show number/bytes of extents of each size that are dirty, muzzy, retained.
This commit is contained in:
parent
33f1aa5bad
commit
c14e6c0819
@ -433,10 +433,11 @@ for (i = 0; i < nbins; i++) {
|
|||||||
arena statistics, respectively; <quote>b</quote> and <quote>l</quote> can
|
arena statistics, respectively; <quote>b</quote> and <quote>l</quote> can
|
||||||
be specified to omit per size class statistics for bins and large objects,
|
be specified to omit per size class statistics for bins and large objects,
|
||||||
respectively; <quote>x</quote> can be specified to omit all mutex
|
respectively; <quote>x</quote> can be specified to omit all mutex
|
||||||
statistics. Unrecognized characters are silently ignored. Note that
|
statistics; <quote>e</quote> can be used to omit extent statistics.
|
||||||
thread caching may prevent some statistics from being completely up to
|
Unrecognized characters are silently ignored. Note that thread caching
|
||||||
date, since extra locking would be required to merge counters that track
|
may prevent some statistics from being completely up to date, since extra
|
||||||
thread cache operations.</para>
|
locking would be required to merge counters that track thread cache
|
||||||
|
operations.</para>
|
||||||
|
|
||||||
<para>The <function>malloc_usable_size()</function> function
|
<para>The <function>malloc_usable_size()</function> function
|
||||||
returns the usable size of the allocation pointed to by
|
returns the usable size of the allocation pointed to by
|
||||||
@ -2925,6 +2926,30 @@ struct extent_hooks_s {
|
|||||||
counters</link>.</para></listitem>
|
counters</link>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="stats.arenas.i.extents.n">
|
||||||
|
<term>
|
||||||
|
<mallctl>stats.arenas.<i>.extents.<j>.n{extent_type}</mallctl>
|
||||||
|
(<type>size_t</type>)
|
||||||
|
<literal>r-</literal>
|
||||||
|
[<option>--enable-stats</option>]
|
||||||
|
</term>
|
||||||
|
<listitem><para> Number of extents of the given type in this arena in
|
||||||
|
the bucket corresponding to page size index <j>. The extent type
|
||||||
|
is one of dirty, muzzy, or retained.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="stats.arenas.i.extents.bytes">
|
||||||
|
<term>
|
||||||
|
<mallctl>stats.arenas.<i>.extents.<j>.{extent_type}_bytes</mallctl>
|
||||||
|
(<type>size_t</type>)
|
||||||
|
<literal>r-</literal>
|
||||||
|
[<option>--enable-stats</option>]
|
||||||
|
</term>
|
||||||
|
<listitem><para> Sum of the bytes managed by extents of the given type
|
||||||
|
in this arena in the bucket corresponding to page size index <j>.
|
||||||
|
The extent type is one of dirty, muzzy, or retained.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="stats.arenas.i.lextents.j.nmalloc">
|
<varlistentry id="stats.arenas.i.lextents.j.nmalloc">
|
||||||
<term>
|
<term>
|
||||||
<mallctl>stats.arenas.<i>.lextents.<j>.nmalloc</mallctl>
|
<mallctl>stats.arenas.<i>.lextents.<j>.nmalloc</mallctl>
|
||||||
|
@ -25,7 +25,8 @@ void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena,
|
|||||||
void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
||||||
const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
|
const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
|
||||||
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
|
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
|
||||||
bin_stats_t *bstats, arena_stats_large_t *lstats);
|
bin_stats_t *bstats, arena_stats_large_t *lstats,
|
||||||
|
arena_stats_extents_t *estats);
|
||||||
void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena,
|
void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena,
|
||||||
extent_hooks_t **r_extent_hooks, extent_t *extent);
|
extent_hooks_t **r_extent_hooks, extent_t *extent);
|
||||||
#ifdef JEMALLOC_JET
|
#ifdef JEMALLOC_JET
|
||||||
|
@ -50,6 +50,22 @@ struct arena_stats_decay_s {
|
|||||||
arena_stats_u64_t purged;
|
arena_stats_u64_t purged;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct arena_stats_extents_s arena_stats_extents_t;
|
||||||
|
struct arena_stats_extents_s {
|
||||||
|
/*
|
||||||
|
* Stats for a given index in the range [0, SC_NPSIZES] in an extents_t.
|
||||||
|
* We track both bytes and # of extents: two extents in the same bucket
|
||||||
|
* may have different sizes if adjacent size classes differ by more than
|
||||||
|
* a page, so bytes cannot always be derived from # of extents.
|
||||||
|
*/
|
||||||
|
atomic_zu_t ndirty;
|
||||||
|
atomic_zu_t dirty_bytes;
|
||||||
|
atomic_zu_t nmuzzy;
|
||||||
|
atomic_zu_t muzzy_bytes;
|
||||||
|
atomic_zu_t nretained;
|
||||||
|
atomic_zu_t retained_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arena stats. Note that fields marked "derived" are not directly maintained
|
* Arena stats. Note that fields marked "derived" are not directly maintained
|
||||||
* within the arena code; rather their values are derived during stats merge
|
* within the arena code; rather their values are derived during stats merge
|
||||||
|
@ -42,6 +42,7 @@ typedef struct ctl_arena_stats_s {
|
|||||||
|
|
||||||
bin_stats_t bstats[SC_NBINS];
|
bin_stats_t bstats[SC_NBINS];
|
||||||
arena_stats_large_t lstats[SC_NSIZES - SC_NBINS];
|
arena_stats_large_t lstats[SC_NSIZES - SC_NBINS];
|
||||||
|
arena_stats_extents_t estats[SC_NPSIZES];
|
||||||
} ctl_arena_stats_t;
|
} ctl_arena_stats_t;
|
||||||
|
|
||||||
typedef struct ctl_stats_s {
|
typedef struct ctl_stats_s {
|
||||||
|
@ -31,6 +31,10 @@ bool extents_init(tsdn_t *tsdn, extents_t *extents, extent_state_t state,
|
|||||||
bool delay_coalesce);
|
bool delay_coalesce);
|
||||||
extent_state_t extents_state_get(const extents_t *extents);
|
extent_state_t extents_state_get(const extents_t *extents);
|
||||||
size_t extents_npages_get(extents_t *extents);
|
size_t extents_npages_get(extents_t *extents);
|
||||||
|
/* Get the number of extents in the given page size index. */
|
||||||
|
size_t extents_nextents_get(extents_t *extents, pszind_t ind);
|
||||||
|
/* Get the sum total bytes of the extents in the given page size index. */
|
||||||
|
size_t extents_nbytes_get(extents_t *extents, pszind_t ind);
|
||||||
extent_t *extents_alloc(tsdn_t *tsdn, arena_t *arena,
|
extent_t *extents_alloc(tsdn_t *tsdn, arena_t *arena,
|
||||||
extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr,
|
extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr,
|
||||||
size_t size, size_t pad, size_t alignment, bool slab, szind_t szind,
|
size_t size, size_t pad, size_t alignment, bool slab, szind_t szind,
|
||||||
|
@ -184,6 +184,8 @@ struct extents_s {
|
|||||||
* Synchronization: mtx.
|
* Synchronization: mtx.
|
||||||
*/
|
*/
|
||||||
extent_heap_t heaps[SC_NPSIZES + 1];
|
extent_heap_t heaps[SC_NPSIZES + 1];
|
||||||
|
atomic_zu_t nextents[SC_NPSIZES + 1];
|
||||||
|
atomic_zu_t nbytes[SC_NPSIZES + 1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bitmap for which set bits correspond to non-empty heaps.
|
* Bitmap for which set bits correspond to non-empty heaps.
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
OPTION('a', unmerged, config_stats, false) \
|
OPTION('a', unmerged, config_stats, false) \
|
||||||
OPTION('b', bins, true, false) \
|
OPTION('b', bins, true, false) \
|
||||||
OPTION('l', large, true, false) \
|
OPTION('l', large, true, false) \
|
||||||
OPTION('x', mutex, true, false)
|
OPTION('x', mutex, true, false) \
|
||||||
|
OPTION('e', extents, true, false)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
#define OPTION(o, v, d, s) stats_print_option_num_##v,
|
#define OPTION(o, v, d, s) stats_print_option_num_##v,
|
||||||
|
25
src/arena.c
25
src/arena.c
@ -82,7 +82,8 @@ void
|
|||||||
arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
||||||
const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
|
const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
|
||||||
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
|
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
|
||||||
bin_stats_t *bstats, arena_stats_large_t *lstats) {
|
bin_stats_t *bstats, arena_stats_large_t *lstats,
|
||||||
|
arena_stats_extents_t *estats) {
|
||||||
cassert(config_stats);
|
cassert(config_stats);
|
||||||
|
|
||||||
arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms,
|
arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms,
|
||||||
@ -153,6 +154,28 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
|||||||
curlextents * sz_index2size(SC_NBINS + i));
|
curlextents * sz_index2size(SC_NBINS + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (pszind_t i = 0; i < SC_NPSIZES; i++) {
|
||||||
|
size_t dirty, muzzy, retained, dirty_bytes, muzzy_bytes,
|
||||||
|
retained_bytes;
|
||||||
|
dirty = extents_nextents_get(&arena->extents_dirty, i);
|
||||||
|
muzzy = extents_nextents_get(&arena->extents_muzzy, i);
|
||||||
|
retained = extents_nextents_get(&arena->extents_retained, i);
|
||||||
|
dirty_bytes = extents_nbytes_get(&arena->extents_dirty, i);
|
||||||
|
muzzy_bytes = extents_nbytes_get(&arena->extents_muzzy, i);
|
||||||
|
retained_bytes =
|
||||||
|
extents_nbytes_get(&arena->extents_retained, i);
|
||||||
|
|
||||||
|
atomic_store_zu(&estats[i].ndirty, dirty, ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&estats[i].nmuzzy, muzzy, ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&estats[i].nretained, retained, ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&estats[i].dirty_bytes, dirty_bytes,
|
||||||
|
ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&estats[i].muzzy_bytes, muzzy_bytes,
|
||||||
|
ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&estats[i].retained_bytes, retained_bytes,
|
||||||
|
ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
arena_stats_unlock(tsdn, &arena->stats);
|
arena_stats_unlock(tsdn, &arena->stats);
|
||||||
|
|
||||||
/* tcache_bytes counts currently cached bytes. */
|
/* tcache_bytes counts currently cached bytes. */
|
||||||
|
82
src/ctl.c
82
src/ctl.c
@ -173,6 +173,13 @@ CTL_PROTO(stats_arenas_i_lextents_j_ndalloc)
|
|||||||
CTL_PROTO(stats_arenas_i_lextents_j_nrequests)
|
CTL_PROTO(stats_arenas_i_lextents_j_nrequests)
|
||||||
CTL_PROTO(stats_arenas_i_lextents_j_curlextents)
|
CTL_PROTO(stats_arenas_i_lextents_j_curlextents)
|
||||||
INDEX_PROTO(stats_arenas_i_lextents_j)
|
INDEX_PROTO(stats_arenas_i_lextents_j)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_ndirty)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_nmuzzy)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_nretained)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_dirty_bytes)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_muzzy_bytes)
|
||||||
|
CTL_PROTO(stats_arenas_i_extents_j_retained_bytes)
|
||||||
|
INDEX_PROTO(stats_arenas_i_extents_j)
|
||||||
CTL_PROTO(stats_arenas_i_nthreads)
|
CTL_PROTO(stats_arenas_i_nthreads)
|
||||||
CTL_PROTO(stats_arenas_i_uptime)
|
CTL_PROTO(stats_arenas_i_uptime)
|
||||||
CTL_PROTO(stats_arenas_i_dss)
|
CTL_PROTO(stats_arenas_i_dss)
|
||||||
@ -395,7 +402,6 @@ static const ctl_named_node_t prof_node[] = {
|
|||||||
{NAME("log_start"), CTL(prof_log_start)},
|
{NAME("log_start"), CTL(prof_log_start)},
|
||||||
{NAME("log_stop"), CTL(prof_log_stop)}
|
{NAME("log_stop"), CTL(prof_log_stop)}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ctl_named_node_t stats_arenas_i_small_node[] = {
|
static const ctl_named_node_t stats_arenas_i_small_node[] = {
|
||||||
{NAME("allocated"), CTL(stats_arenas_i_small_allocated)},
|
{NAME("allocated"), CTL(stats_arenas_i_small_allocated)},
|
||||||
{NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)},
|
{NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)},
|
||||||
@ -466,6 +472,23 @@ static const ctl_indexed_node_t stats_arenas_i_lextents_node[] = {
|
|||||||
{INDEX(stats_arenas_i_lextents_j)}
|
{INDEX(stats_arenas_i_lextents_j)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const ctl_named_node_t stats_arenas_i_extents_j_node[] = {
|
||||||
|
{NAME("ndirty"), CTL(stats_arenas_i_extents_j_ndirty)},
|
||||||
|
{NAME("nmuzzy"), CTL(stats_arenas_i_extents_j_nmuzzy)},
|
||||||
|
{NAME("nretained"), CTL(stats_arenas_i_extents_j_nretained)},
|
||||||
|
{NAME("dirty_bytes"), CTL(stats_arenas_i_extents_j_dirty_bytes)},
|
||||||
|
{NAME("muzzy_bytes"), CTL(stats_arenas_i_extents_j_muzzy_bytes)},
|
||||||
|
{NAME("retained_bytes"), CTL(stats_arenas_i_extents_j_retained_bytes)}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ctl_named_node_t super_stats_arenas_i_extents_j_node[] = {
|
||||||
|
{NAME(""), CHILD(named, stats_arenas_i_extents_j)}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ctl_indexed_node_t stats_arenas_i_extents_node[] = {
|
||||||
|
{INDEX(stats_arenas_i_extents_j)}
|
||||||
|
};
|
||||||
|
|
||||||
#define OP(mtx) MUTEX_PROF_DATA_NODE(arenas_i_mutexes_##mtx)
|
#define OP(mtx) MUTEX_PROF_DATA_NODE(arenas_i_mutexes_##mtx)
|
||||||
MUTEX_PROF_ARENA_MUTEXES
|
MUTEX_PROF_ARENA_MUTEXES
|
||||||
#undef OP
|
#undef OP
|
||||||
@ -502,6 +525,7 @@ static const ctl_named_node_t stats_arenas_i_node[] = {
|
|||||||
{NAME("large"), CHILD(named, stats_arenas_i_large)},
|
{NAME("large"), CHILD(named, stats_arenas_i_large)},
|
||||||
{NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
|
{NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
|
||||||
{NAME("lextents"), CHILD(indexed, stats_arenas_i_lextents)},
|
{NAME("lextents"), CHILD(indexed, stats_arenas_i_lextents)},
|
||||||
|
{NAME("extents"), CHILD(indexed, stats_arenas_i_extents)},
|
||||||
{NAME("mutexes"), CHILD(named, stats_arenas_i_mutexes)}
|
{NAME("mutexes"), CHILD(named, stats_arenas_i_mutexes)}
|
||||||
};
|
};
|
||||||
static const ctl_named_node_t super_stats_arenas_i_node[] = {
|
static const ctl_named_node_t super_stats_arenas_i_node[] = {
|
||||||
@ -718,6 +742,8 @@ ctl_arena_clear(ctl_arena_t *ctl_arena) {
|
|||||||
sizeof(bin_stats_t));
|
sizeof(bin_stats_t));
|
||||||
memset(ctl_arena->astats->lstats, 0, (SC_NSIZES - SC_NBINS) *
|
memset(ctl_arena->astats->lstats, 0, (SC_NSIZES - SC_NBINS) *
|
||||||
sizeof(arena_stats_large_t));
|
sizeof(arena_stats_large_t));
|
||||||
|
memset(ctl_arena->astats->estats, 0, SC_NPSIZES *
|
||||||
|
sizeof(arena_stats_extents_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,7 +757,7 @@ ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) {
|
|||||||
&ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
|
&ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
|
||||||
&ctl_arena->pdirty, &ctl_arena->pmuzzy,
|
&ctl_arena->pdirty, &ctl_arena->pmuzzy,
|
||||||
&ctl_arena->astats->astats, ctl_arena->astats->bstats,
|
&ctl_arena->astats->astats, ctl_arena->astats->bstats,
|
||||||
ctl_arena->astats->lstats);
|
ctl_arena->astats->lstats, ctl_arena->astats->estats);
|
||||||
|
|
||||||
for (i = 0; i < SC_NBINS; i++) {
|
for (i = 0; i < SC_NBINS; i++) {
|
||||||
ctl_arena->astats->allocated_small +=
|
ctl_arena->astats->allocated_small +=
|
||||||
@ -845,6 +871,7 @@ MUTEX_PROF_ARENA_MUTEXES
|
|||||||
sdstats->astats.uptime = astats->astats.uptime;
|
sdstats->astats.uptime = astats->astats.uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merge bin stats. */
|
||||||
for (i = 0; i < SC_NBINS; i++) {
|
for (i = 0; i < SC_NBINS; i++) {
|
||||||
sdstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
|
sdstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
|
||||||
sdstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
|
sdstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
|
||||||
@ -871,6 +898,7 @@ MUTEX_PROF_ARENA_MUTEXES
|
|||||||
&astats->bstats[i].mutex_data);
|
&astats->bstats[i].mutex_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merge stats for large allocations. */
|
||||||
for (i = 0; i < SC_NSIZES - SC_NBINS; i++) {
|
for (i = 0; i < SC_NSIZES - SC_NBINS; i++) {
|
||||||
ctl_accum_arena_stats_u64(&sdstats->lstats[i].nmalloc,
|
ctl_accum_arena_stats_u64(&sdstats->lstats[i].nmalloc,
|
||||||
&astats->lstats[i].nmalloc);
|
&astats->lstats[i].nmalloc);
|
||||||
@ -885,6 +913,22 @@ MUTEX_PROF_ARENA_MUTEXES
|
|||||||
assert(astats->lstats[i].curlextents == 0);
|
assert(astats->lstats[i].curlextents == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merge extents stats. */
|
||||||
|
for (i = 0; i < SC_NPSIZES; i++) {
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].ndirty,
|
||||||
|
&astats->estats[i].ndirty);
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].nmuzzy,
|
||||||
|
&astats->estats[i].nmuzzy);
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].nretained,
|
||||||
|
&astats->estats[i].nretained);
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].dirty_bytes,
|
||||||
|
&astats->estats[i].dirty_bytes);
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].muzzy_bytes,
|
||||||
|
&astats->estats[i].muzzy_bytes);
|
||||||
|
accum_atomic_zu(&sdstats->estats[i].retained_bytes,
|
||||||
|
&astats->estats[i].retained_bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2918,6 +2962,40 @@ stats_arenas_i_lextents_j_index(tsdn_t *tsdn, const size_t *mib,
|
|||||||
return super_stats_arenas_i_lextents_j_node;
|
return super_stats_arenas_i_lextents_j_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_ndirty,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].ndirty,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nmuzzy,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].nmuzzy,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nretained,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].nretained,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_dirty_bytes,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].dirty_bytes,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_muzzy_bytes,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].muzzy_bytes,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_retained_bytes,
|
||||||
|
atomic_load_zu(
|
||||||
|
&arenas_i(mib[2])->astats->estats[mib[4]].retained_bytes,
|
||||||
|
ATOMIC_RELAXED), size_t);
|
||||||
|
|
||||||
|
static const ctl_named_node_t *
|
||||||
|
stats_arenas_i_extents_j_index(tsdn_t *tsdn, const size_t *mib,
|
||||||
|
size_t miblen, size_t j) {
|
||||||
|
if (j >= SC_NPSIZES) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return super_stats_arenas_i_extents_j_node;
|
||||||
|
}
|
||||||
|
|
||||||
static const ctl_named_node_t *
|
static const ctl_named_node_t *
|
||||||
stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
|
stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
|
||||||
size_t miblen, size_t i) {
|
size_t miblen, size_t i) {
|
||||||
|
36
src/extent.c
36
src/extent.c
@ -309,6 +309,32 @@ extents_npages_get(extents_t *extents) {
|
|||||||
return atomic_load_zu(&extents->npages, ATOMIC_RELAXED);
|
return atomic_load_zu(&extents->npages, ATOMIC_RELAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
extents_nextents_get(extents_t *extents, pszind_t pind) {
|
||||||
|
return atomic_load_zu(&extents->nextents[pind], ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
extents_nbytes_get(extents_t *extents, pszind_t pind) {
|
||||||
|
return atomic_load_zu(&extents->nbytes[pind], ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extents_stats_add(extents_t *extent, pszind_t pind, size_t sz) {
|
||||||
|
size_t cur = atomic_load_zu(&extent->nextents[pind], ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&extent->nextents[pind], cur + 1, ATOMIC_RELAXED);
|
||||||
|
cur = atomic_load_zu(&extent->nbytes[pind], ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&extent->nbytes[pind], cur + sz, ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extents_stats_sub(extents_t *extent, pszind_t pind, size_t sz) {
|
||||||
|
size_t cur = atomic_load_zu(&extent->nextents[pind], ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&extent->nextents[pind], cur - 1, ATOMIC_RELAXED);
|
||||||
|
cur = atomic_load_zu(&extent->nbytes[pind], ATOMIC_RELAXED);
|
||||||
|
atomic_store_zu(&extent->nbytes[pind], cur - sz, ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) {
|
extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) {
|
||||||
malloc_mutex_assert_owner(tsdn, &extents->mtx);
|
malloc_mutex_assert_owner(tsdn, &extents->mtx);
|
||||||
@ -322,6 +348,11 @@ extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) {
|
|||||||
(size_t)pind);
|
(size_t)pind);
|
||||||
}
|
}
|
||||||
extent_heap_insert(&extents->heaps[pind], extent);
|
extent_heap_insert(&extents->heaps[pind], extent);
|
||||||
|
|
||||||
|
if (config_stats) {
|
||||||
|
extents_stats_add(extents, pind, size);
|
||||||
|
}
|
||||||
|
|
||||||
extent_list_append(&extents->lru, extent);
|
extent_list_append(&extents->lru, extent);
|
||||||
size_t npages = size >> LG_PAGE;
|
size_t npages = size >> LG_PAGE;
|
||||||
/*
|
/*
|
||||||
@ -344,6 +375,11 @@ extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent) {
|
|||||||
size_t psz = extent_size_quantize_floor(size);
|
size_t psz = extent_size_quantize_floor(size);
|
||||||
pszind_t pind = sz_psz2ind(psz);
|
pszind_t pind = sz_psz2ind(psz);
|
||||||
extent_heap_remove(&extents->heaps[pind], extent);
|
extent_heap_remove(&extents->heaps[pind], extent);
|
||||||
|
|
||||||
|
if (config_stats) {
|
||||||
|
extents_stats_sub(extents, pind, size);
|
||||||
|
}
|
||||||
|
|
||||||
if (extent_heap_empty(&extents->heaps[pind])) {
|
if (extent_heap_empty(&extents->heaps[pind])) {
|
||||||
bitmap_set(extents->bitmap, &extents_bitmap_info,
|
bitmap_set(extents->bitmap, &extents_bitmap_info,
|
||||||
(size_t)pind);
|
(size_t)pind);
|
||||||
|
117
src/stats.c
117
src/stats.c
@ -494,6 +494,108 @@ stats_arena_lextents_print(emitter_t *emitter, unsigned i) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stats_arena_extents_print(emitter_t *emitter, unsigned i) {
|
||||||
|
unsigned j;
|
||||||
|
bool in_gap, in_gap_prev;
|
||||||
|
emitter_row_t header_row;
|
||||||
|
emitter_row_init(&header_row);
|
||||||
|
emitter_row_t row;
|
||||||
|
emitter_row_init(&row);
|
||||||
|
#define COL(name, left_or_right, col_width, etype) \
|
||||||
|
emitter_col_t header_##name; \
|
||||||
|
emitter_col_init(&header_##name, &header_row); \
|
||||||
|
header_##name.justify = emitter_justify_##left_or_right; \
|
||||||
|
header_##name.width = col_width; \
|
||||||
|
header_##name.type = emitter_type_title; \
|
||||||
|
header_##name.str_val = #name; \
|
||||||
|
\
|
||||||
|
emitter_col_t col_##name; \
|
||||||
|
emitter_col_init(&col_##name, &row); \
|
||||||
|
col_##name.justify = emitter_justify_##left_or_right; \
|
||||||
|
col_##name.width = col_width; \
|
||||||
|
col_##name.type = emitter_type_##etype;
|
||||||
|
|
||||||
|
COL(size, right, 20, size)
|
||||||
|
COL(ind, right, 4, unsigned)
|
||||||
|
COL(ndirty, right, 13, size)
|
||||||
|
COL(dirty, right, 13, size)
|
||||||
|
COL(nmuzzy, right, 13, size)
|
||||||
|
COL(muzzy, right, 13, size)
|
||||||
|
COL(nretained, right, 13, size)
|
||||||
|
COL(retained, right, 13, size)
|
||||||
|
COL(ntotal, right, 13, size)
|
||||||
|
COL(total, right, 13, size)
|
||||||
|
#undef COL
|
||||||
|
|
||||||
|
/* Label this section. */
|
||||||
|
header_size.width -= 8;
|
||||||
|
emitter_table_printf(emitter, "extents:");
|
||||||
|
emitter_table_row(emitter, &header_row);
|
||||||
|
emitter_json_array_kv_begin(emitter, "extents");
|
||||||
|
|
||||||
|
in_gap = false;
|
||||||
|
for (j = 0; j < SC_NPSIZES; j++) {
|
||||||
|
size_t ndirty, nmuzzy, nretained, total, dirty_bytes,
|
||||||
|
muzzy_bytes, retained_bytes, total_bytes;
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.ndirty", i, j,
|
||||||
|
&ndirty, size_t);
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.nmuzzy", i, j,
|
||||||
|
&nmuzzy, size_t);
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.nretained", i, j,
|
||||||
|
&nretained, size_t);
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.dirty_bytes", i, j,
|
||||||
|
&dirty_bytes, size_t);
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.muzzy_bytes", i, j,
|
||||||
|
&muzzy_bytes, size_t);
|
||||||
|
CTL_M2_M4_GET("stats.arenas.0.extents.0.retained_bytes", i, j,
|
||||||
|
&retained_bytes, size_t);
|
||||||
|
total = ndirty + nmuzzy + nretained;
|
||||||
|
total_bytes = dirty_bytes + muzzy_bytes + retained_bytes;
|
||||||
|
|
||||||
|
in_gap_prev = in_gap;
|
||||||
|
in_gap = (total == 0);
|
||||||
|
|
||||||
|
if (in_gap_prev && !in_gap) {
|
||||||
|
emitter_table_printf(emitter,
|
||||||
|
" ---\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter_json_object_begin(emitter);
|
||||||
|
emitter_json_kv(emitter, "ndirty", emitter_type_size, &ndirty);
|
||||||
|
emitter_json_kv(emitter, "nmuzzy", emitter_type_size, &nmuzzy);
|
||||||
|
emitter_json_kv(emitter, "nretained", emitter_type_size,
|
||||||
|
&nretained);
|
||||||
|
|
||||||
|
emitter_json_kv(emitter, "dirty_bytes", emitter_type_size,
|
||||||
|
&dirty_bytes);
|
||||||
|
emitter_json_kv(emitter, "muzzy_bytes", emitter_type_size,
|
||||||
|
&muzzy_bytes);
|
||||||
|
emitter_json_kv(emitter, "retained_bytes", emitter_type_size,
|
||||||
|
&retained_bytes);
|
||||||
|
emitter_json_object_end(emitter);
|
||||||
|
|
||||||
|
col_size.size_val = sz_pind2sz(j);
|
||||||
|
col_ind.size_val = j;
|
||||||
|
col_ndirty.size_val = ndirty;
|
||||||
|
col_dirty.size_val = dirty_bytes;
|
||||||
|
col_nmuzzy.size_val = nmuzzy;
|
||||||
|
col_muzzy.size_val = muzzy_bytes;
|
||||||
|
col_nretained.size_val = nretained;
|
||||||
|
col_retained.size_val = retained_bytes;
|
||||||
|
col_ntotal.size_val = total;
|
||||||
|
col_total.size_val = total_bytes;
|
||||||
|
|
||||||
|
if (!in_gap) {
|
||||||
|
emitter_table_row(emitter, &row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emitter_json_array_end(emitter); /* Close "extents". */
|
||||||
|
if (in_gap) {
|
||||||
|
emitter_table_printf(emitter, " ---\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind) {
|
stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind) {
|
||||||
emitter_row_t row;
|
emitter_row_t row;
|
||||||
@ -521,7 +623,7 @@ stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||||
bool mutex) {
|
bool mutex, bool extents) {
|
||||||
unsigned nthreads;
|
unsigned nthreads;
|
||||||
const char *dss;
|
const char *dss;
|
||||||
ssize_t dirty_decay_ms, muzzy_decay_ms;
|
ssize_t dirty_decay_ms, muzzy_decay_ms;
|
||||||
@ -820,6 +922,9 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
|||||||
if (large) {
|
if (large) {
|
||||||
stats_arena_lextents_print(emitter, i);
|
stats_arena_lextents_print(emitter, i);
|
||||||
}
|
}
|
||||||
|
if (extents) {
|
||||||
|
stats_arena_extents_print(emitter, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1066,7 +1171,7 @@ stats_general_print(emitter_t *emitter) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||||
bool unmerged, bool bins, bool large, bool mutex) {
|
bool unmerged, bool bins, bool large, bool mutex, bool extents) {
|
||||||
/*
|
/*
|
||||||
* These should be deleted. We keep them around for a while, to aid in
|
* These should be deleted. We keep them around for a while, to aid in
|
||||||
* the transition to the emitter code.
|
* the transition to the emitter code.
|
||||||
@ -1187,7 +1292,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
|||||||
emitter_table_printf(emitter, "Merged arenas stats:\n");
|
emitter_table_printf(emitter, "Merged arenas stats:\n");
|
||||||
emitter_json_object_kv_begin(emitter, "merged");
|
emitter_json_object_kv_begin(emitter, "merged");
|
||||||
stats_arena_print(emitter, MALLCTL_ARENAS_ALL, bins,
|
stats_arena_print(emitter, MALLCTL_ARENAS_ALL, bins,
|
||||||
large, mutex);
|
large, mutex, extents);
|
||||||
emitter_json_object_end(emitter); /* Close "merged". */
|
emitter_json_object_end(emitter); /* Close "merged". */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,7 +1303,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
|||||||
"Destroyed arenas stats:\n");
|
"Destroyed arenas stats:\n");
|
||||||
emitter_json_object_kv_begin(emitter, "destroyed");
|
emitter_json_object_kv_begin(emitter, "destroyed");
|
||||||
stats_arena_print(emitter, MALLCTL_ARENAS_DESTROYED,
|
stats_arena_print(emitter, MALLCTL_ARENAS_DESTROYED,
|
||||||
bins, large, mutex);
|
bins, large, mutex, extents);
|
||||||
emitter_json_object_end(emitter); /* Close "destroyed". */
|
emitter_json_object_end(emitter); /* Close "destroyed". */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1214,7 +1319,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
|||||||
emitter_table_printf(emitter,
|
emitter_table_printf(emitter,
|
||||||
"arenas[%s]:\n", arena_ind_str);
|
"arenas[%s]:\n", arena_ind_str);
|
||||||
stats_arena_print(emitter, i, bins,
|
stats_arena_print(emitter, i, bins,
|
||||||
large, mutex);
|
large, mutex, extents);
|
||||||
/* Close "<arena-ind>". */
|
/* Close "<arena-ind>". */
|
||||||
emitter_json_object_end(emitter);
|
emitter_json_object_end(emitter);
|
||||||
}
|
}
|
||||||
@ -1280,7 +1385,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
|||||||
}
|
}
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
stats_print_helper(&emitter, merged, destroyed, unmerged,
|
stats_print_helper(&emitter, merged, destroyed, unmerged,
|
||||||
bins, large, mutex);
|
bins, large, mutex, extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitter_json_object_end(&emitter); /* Closes the "jemalloc" dict. */
|
emitter_json_object_end(&emitter); /* Closes the "jemalloc" dict. */
|
||||||
|
Loading…
Reference in New Issue
Block a user