Add the stats.retained and stats.arenas.<i>.retained statistics.
This resolves #367.
This commit is contained in:
parent
c1e9cf47f9
commit
04c3c0f9a0
@ -2186,6 +2186,25 @@ typedef struct {
|
|||||||
linkend="stats.resident"><mallctl>stats.resident</mallctl></link>.</para></listitem>
|
linkend="stats.resident"><mallctl>stats.resident</mallctl></link>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="stats.retained">
|
||||||
|
<term>
|
||||||
|
<mallctl>stats.retained</mallctl>
|
||||||
|
(<type>size_t</type>)
|
||||||
|
<literal>r-</literal>
|
||||||
|
[<option>--enable-stats</option>]
|
||||||
|
</term>
|
||||||
|
<listitem><para>Total number of bytes in virtual memory mappings that
|
||||||
|
were retained rather than being returned to the operating system via
|
||||||
|
e.g. <citerefentry><refentrytitle>munmap</refentrytitle>
|
||||||
|
<manvolnum>2</manvolnum></citerefentry>. Retained virtual memory is
|
||||||
|
typically untouched, decommitted, or purged, so it has no strongly
|
||||||
|
associated physical memory (see <link
|
||||||
|
linkend="arena.i.chunk_hooks">chunk hooks</link> for details). Retained
|
||||||
|
memory is excluded from mapped memory statistics, e.g. <link
|
||||||
|
linkend="stats.mapped"><mallctl>stats.mapped</mallctl></link>.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="stats.arenas.i.dss">
|
<varlistentry id="stats.arenas.i.dss">
|
||||||
<term>
|
<term>
|
||||||
<mallctl>stats.arenas.<i>.dss</mallctl>
|
<mallctl>stats.arenas.<i>.dss</mallctl>
|
||||||
@ -2266,6 +2285,18 @@ typedef struct {
|
|||||||
<listitem><para>Number of mapped bytes.</para></listitem>
|
<listitem><para>Number of mapped bytes.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="stats.arenas.i.retained">
|
||||||
|
<term>
|
||||||
|
<mallctl>stats.arenas.<i>.retained</mallctl>
|
||||||
|
(<type>size_t</type>)
|
||||||
|
<literal>r-</literal>
|
||||||
|
[<option>--enable-stats</option>]
|
||||||
|
</term>
|
||||||
|
<listitem><para>Number of retained bytes. See <link
|
||||||
|
linkend="stats.retained"><mallctl>stats.retained</mallctl></link> for
|
||||||
|
details.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="stats.arenas.i.metadata.mapped">
|
<varlistentry id="stats.arenas.i.metadata.mapped">
|
||||||
<term>
|
<term>
|
||||||
<mallctl>stats.arenas.<i>.metadata.mapped</mallctl>
|
<mallctl>stats.arenas.<i>.metadata.mapped</mallctl>
|
||||||
|
@ -61,6 +61,7 @@ struct ctl_stats_s {
|
|||||||
size_t metadata;
|
size_t metadata;
|
||||||
size_t resident;
|
size_t resident;
|
||||||
size_t mapped;
|
size_t mapped;
|
||||||
|
size_t retained;
|
||||||
unsigned narenas;
|
unsigned narenas;
|
||||||
ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */
|
ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */
|
||||||
};
|
};
|
||||||
|
@ -102,6 +102,14 @@ struct arena_stats_s {
|
|||||||
/* Number of bytes currently mapped. */
|
/* Number of bytes currently mapped. */
|
||||||
size_t mapped;
|
size_t mapped;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of bytes currently retained as a side effect of munmap() being
|
||||||
|
* disabled/bypassed. Retained bytes are technically mapped (though
|
||||||
|
* always decommitted or purged), but they are excluded from the mapped
|
||||||
|
* statistic (above).
|
||||||
|
*/
|
||||||
|
size_t retained;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Total number of purge sweeps, total number of madvise calls made,
|
* Total number of purge sweeps, total number of madvise calls made,
|
||||||
* and total pages purged in order to keep dirty unused memory under
|
* and total pages purged in order to keep dirty unused memory under
|
||||||
|
@ -3414,6 +3414,7 @@ arena_stats_merge(tsd_t *tsd, arena_t *arena, unsigned *nthreads,
|
|||||||
decay_time, nactive, ndirty);
|
decay_time, nactive, ndirty);
|
||||||
|
|
||||||
astats->mapped += arena->stats.mapped;
|
astats->mapped += arena->stats.mapped;
|
||||||
|
astats->retained += arena->stats.retained;
|
||||||
astats->npurge += arena->stats.npurge;
|
astats->npurge += arena->stats.npurge;
|
||||||
astats->nmadvise += arena->stats.nmadvise;
|
astats->nmadvise += arena->stats.nmadvise;
|
||||||
astats->purged += arena->stats.purged;
|
astats->purged += arena->stats.purged;
|
||||||
|
13
src/chunk.c
13
src/chunk.c
@ -444,15 +444,21 @@ static void *
|
|||||||
chunk_alloc_retained(tsd_t *tsd, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
chunk_alloc_retained(tsd_t *tsd, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
||||||
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
|
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
|
||||||
{
|
{
|
||||||
|
void *ret;
|
||||||
|
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
assert((size & chunksize_mask) == 0);
|
assert((size & chunksize_mask) == 0);
|
||||||
assert(alignment != 0);
|
assert(alignment != 0);
|
||||||
assert((alignment & chunksize_mask) == 0);
|
assert((alignment & chunksize_mask) == 0);
|
||||||
|
|
||||||
return (chunk_recycle(tsd, arena, chunk_hooks,
|
ret = chunk_recycle(tsd, arena, chunk_hooks,
|
||||||
&arena->chunks_szad_retained, &arena->chunks_ad_retained, false,
|
&arena->chunks_szad_retained, &arena->chunks_ad_retained, false,
|
||||||
new_addr, size, alignment, zero, commit, true));
|
new_addr, size, alignment, zero, commit, true);
|
||||||
|
|
||||||
|
if (config_stats && ret != NULL)
|
||||||
|
arena->stats.retained -= size;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@ -617,6 +623,9 @@ chunk_dalloc_wrapper(tsd_t *tsd, arena_t *arena, chunk_hooks_t *chunk_hooks,
|
|||||||
arena->ind);
|
arena->ind);
|
||||||
chunk_record(tsd, arena, chunk_hooks, &arena->chunks_szad_retained,
|
chunk_record(tsd, arena, chunk_hooks, &arena->chunks_szad_retained,
|
||||||
&arena->chunks_ad_retained, false, chunk, size, zeroed, committed);
|
&arena->chunks_ad_retained, false, chunk, size, zeroed, committed);
|
||||||
|
|
||||||
|
if (config_stats)
|
||||||
|
arena->stats.retained += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
10
src/ctl.c
10
src/ctl.c
@ -192,6 +192,7 @@ CTL_PROTO(stats_arenas_i_decay_time)
|
|||||||
CTL_PROTO(stats_arenas_i_pactive)
|
CTL_PROTO(stats_arenas_i_pactive)
|
||||||
CTL_PROTO(stats_arenas_i_pdirty)
|
CTL_PROTO(stats_arenas_i_pdirty)
|
||||||
CTL_PROTO(stats_arenas_i_mapped)
|
CTL_PROTO(stats_arenas_i_mapped)
|
||||||
|
CTL_PROTO(stats_arenas_i_retained)
|
||||||
CTL_PROTO(stats_arenas_i_npurge)
|
CTL_PROTO(stats_arenas_i_npurge)
|
||||||
CTL_PROTO(stats_arenas_i_nmadvise)
|
CTL_PROTO(stats_arenas_i_nmadvise)
|
||||||
CTL_PROTO(stats_arenas_i_purged)
|
CTL_PROTO(stats_arenas_i_purged)
|
||||||
@ -204,6 +205,7 @@ CTL_PROTO(stats_active)
|
|||||||
CTL_PROTO(stats_metadata)
|
CTL_PROTO(stats_metadata)
|
||||||
CTL_PROTO(stats_resident)
|
CTL_PROTO(stats_resident)
|
||||||
CTL_PROTO(stats_mapped)
|
CTL_PROTO(stats_mapped)
|
||||||
|
CTL_PROTO(stats_retained)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* mallctl tree. */
|
/* mallctl tree. */
|
||||||
@ -458,6 +460,7 @@ static const ctl_named_node_t stats_arenas_i_node[] = {
|
|||||||
{NAME("pactive"), CTL(stats_arenas_i_pactive)},
|
{NAME("pactive"), CTL(stats_arenas_i_pactive)},
|
||||||
{NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
|
{NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
|
||||||
{NAME("mapped"), CTL(stats_arenas_i_mapped)},
|
{NAME("mapped"), CTL(stats_arenas_i_mapped)},
|
||||||
|
{NAME("retained"), CTL(stats_arenas_i_retained)},
|
||||||
{NAME("npurge"), CTL(stats_arenas_i_npurge)},
|
{NAME("npurge"), CTL(stats_arenas_i_npurge)},
|
||||||
{NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)},
|
{NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)},
|
||||||
{NAME("purged"), CTL(stats_arenas_i_purged)},
|
{NAME("purged"), CTL(stats_arenas_i_purged)},
|
||||||
@ -484,6 +487,7 @@ static const ctl_named_node_t stats_node[] = {
|
|||||||
{NAME("metadata"), CTL(stats_metadata)},
|
{NAME("metadata"), CTL(stats_metadata)},
|
||||||
{NAME("resident"), CTL(stats_resident)},
|
{NAME("resident"), CTL(stats_resident)},
|
||||||
{NAME("mapped"), CTL(stats_mapped)},
|
{NAME("mapped"), CTL(stats_mapped)},
|
||||||
|
{NAME("retained"), CTL(stats_retained)},
|
||||||
{NAME("arenas"), CHILD(indexed, stats_arenas)}
|
{NAME("arenas"), CHILD(indexed, stats_arenas)}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -591,6 +595,7 @@ ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
|
|||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
sstats->astats.mapped += astats->astats.mapped;
|
sstats->astats.mapped += astats->astats.mapped;
|
||||||
|
sstats->astats.retained += astats->astats.retained;
|
||||||
sstats->astats.npurge += astats->astats.npurge;
|
sstats->astats.npurge += astats->astats.npurge;
|
||||||
sstats->astats.nmadvise += astats->astats.nmadvise;
|
sstats->astats.nmadvise += astats->astats.nmadvise;
|
||||||
sstats->astats.purged += astats->astats.purged;
|
sstats->astats.purged += astats->astats.purged;
|
||||||
@ -745,6 +750,8 @@ ctl_refresh(tsd_t *tsd)
|
|||||||
ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
|
ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
|
||||||
ctl_stats.mapped = base_mapped +
|
ctl_stats.mapped = base_mapped +
|
||||||
ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
|
ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
|
||||||
|
ctl_stats.retained =
|
||||||
|
ctl_stats.arenas[ctl_stats.narenas].astats.retained;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctl_epoch++;
|
ctl_epoch++;
|
||||||
@ -2108,6 +2115,7 @@ CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
|
|||||||
CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
|
CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
|
||||||
CTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
|
CTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
|
||||||
CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
|
CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
|
||||||
|
CTL_RO_CGEN(config_stats, stats_retained, ctl_stats.retained, size_t)
|
||||||
|
|
||||||
CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
|
CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
|
||||||
CTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
|
CTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
|
||||||
@ -2119,6 +2127,8 @@ CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
|
|||||||
CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
|
CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
|
||||||
CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
|
CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
|
||||||
ctl_stats.arenas[mib[2]].astats.mapped, size_t)
|
ctl_stats.arenas[mib[2]].astats.mapped, size_t)
|
||||||
|
CTL_RO_CGEN(config_stats, stats_arenas_i_retained,
|
||||||
|
ctl_stats.arenas[mib[2]].astats.retained, size_t)
|
||||||
CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
|
CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
|
||||||
ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
|
ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
|
||||||
CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
|
CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
|
||||||
|
12
src/stats.c
12
src/stats.c
@ -259,7 +259,7 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
|||||||
unsigned nthreads;
|
unsigned nthreads;
|
||||||
const char *dss;
|
const char *dss;
|
||||||
ssize_t lg_dirty_mult, decay_time;
|
ssize_t lg_dirty_mult, decay_time;
|
||||||
size_t page, pactive, pdirty, mapped;
|
size_t page, pactive, pdirty, mapped, retained;
|
||||||
size_t metadata_mapped, metadata_allocated;
|
size_t metadata_mapped, metadata_allocated;
|
||||||
uint64_t npurge, nmadvise, purged;
|
uint64_t npurge, nmadvise, purged;
|
||||||
size_t small_allocated;
|
size_t small_allocated;
|
||||||
@ -349,6 +349,9 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
|||||||
CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t);
|
CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t);
|
||||||
malloc_cprintf(write_cb, cbopaque,
|
malloc_cprintf(write_cb, cbopaque,
|
||||||
"mapped: %12zu\n", mapped);
|
"mapped: %12zu\n", mapped);
|
||||||
|
CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t);
|
||||||
|
malloc_cprintf(write_cb, cbopaque,
|
||||||
|
"retained: %12zu\n", retained);
|
||||||
CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped,
|
CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped,
|
||||||
size_t);
|
size_t);
|
||||||
CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated,
|
CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated,
|
||||||
@ -597,7 +600,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
|||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
size_t *cactive;
|
size_t *cactive;
|
||||||
size_t allocated, active, metadata, resident, mapped;
|
size_t allocated, active, metadata, resident, mapped, retained;
|
||||||
|
|
||||||
CTL_GET("stats.cactive", &cactive, size_t *);
|
CTL_GET("stats.cactive", &cactive, size_t *);
|
||||||
CTL_GET("stats.allocated", &allocated, size_t);
|
CTL_GET("stats.allocated", &allocated, size_t);
|
||||||
@ -605,10 +608,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
|||||||
CTL_GET("stats.metadata", &metadata, size_t);
|
CTL_GET("stats.metadata", &metadata, size_t);
|
||||||
CTL_GET("stats.resident", &resident, size_t);
|
CTL_GET("stats.resident", &resident, size_t);
|
||||||
CTL_GET("stats.mapped", &mapped, size_t);
|
CTL_GET("stats.mapped", &mapped, size_t);
|
||||||
|
CTL_GET("stats.retained", &retained, size_t);
|
||||||
malloc_cprintf(write_cb, cbopaque,
|
malloc_cprintf(write_cb, cbopaque,
|
||||||
"Allocated: %zu, active: %zu, metadata: %zu,"
|
"Allocated: %zu, active: %zu, metadata: %zu,"
|
||||||
" resident: %zu, mapped: %zu\n",
|
" resident: %zu, mapped: %zu, retained: %zu\n",
|
||||||
allocated, active, metadata, resident, mapped);
|
allocated, active, metadata, resident, mapped, retained);
|
||||||
malloc_cprintf(write_cb, cbopaque,
|
malloc_cprintf(write_cb, cbopaque,
|
||||||
"Current active ceiling: %zu\n",
|
"Current active ceiling: %zu\n",
|
||||||
atomic_read_z(cactive));
|
atomic_read_z(cactive));
|
||||||
|
Loading…
Reference in New Issue
Block a user