Track the leaked VM space via the abandoned_vm counter.
The counter is 0 unless metadata allocation failed (indicates OOM), and is mainly for sanity checking.
This commit is contained in:
parent
42807fcd9e
commit
4e36ce34c1
@ -112,6 +112,9 @@ struct arena_stats_s {
|
||||
arena_stats_u64_t nflushes_large; /* Derived. */
|
||||
arena_stats_u64_t nrequests_large; /* Derived. */
|
||||
|
||||
/* VM space had to be leaked (undocumented). Normally 0. */
|
||||
atomic_zu_t abandoned_vm;
|
||||
|
||||
/* Number of bytes cached in tcache associated with this arena. */
|
||||
atomic_zu_t tcache_bytes; /* Derived. */
|
||||
|
||||
|
@ -132,6 +132,8 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
|
||||
(((atomic_load_zu(&arena->nactive, ATOMIC_RELAXED) +
|
||||
extents_npages_get(&arena->extents_dirty) +
|
||||
extents_npages_get(&arena->extents_muzzy)) << LG_PAGE)));
|
||||
arena_stats_accum_zu(&astats->abandoned_vm, atomic_load_zu(
|
||||
&arena->stats.abandoned_vm, ATOMIC_RELAXED));
|
||||
|
||||
for (szind_t i = 0; i < SC_NSIZES - SC_NBINS; i++) {
|
||||
uint64_t nmalloc = arena_stats_read_u64(tsdn, &arena->stats,
|
||||
|
@ -210,6 +210,7 @@ CTL_PROTO(stats_arenas_i_internal)
|
||||
CTL_PROTO(stats_arenas_i_metadata_thp)
|
||||
CTL_PROTO(stats_arenas_i_tcache_bytes)
|
||||
CTL_PROTO(stats_arenas_i_resident)
|
||||
CTL_PROTO(stats_arenas_i_abandoned_vm)
|
||||
INDEX_PROTO(stats_arenas_i)
|
||||
CTL_PROTO(stats_allocated)
|
||||
CTL_PROTO(stats_active)
|
||||
@ -543,6 +544,7 @@ static const ctl_named_node_t stats_arenas_i_node[] = {
|
||||
{NAME("metadata_thp"), CTL(stats_arenas_i_metadata_thp)},
|
||||
{NAME("tcache_bytes"), CTL(stats_arenas_i_tcache_bytes)},
|
||||
{NAME("resident"), CTL(stats_arenas_i_resident)},
|
||||
{NAME("abandoned_vm"), CTL(stats_arenas_i_abandoned_vm)},
|
||||
{NAME("small"), CHILD(named, stats_arenas_i_small)},
|
||||
{NAME("large"), CHILD(named, stats_arenas_i_large)},
|
||||
{NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
|
||||
@ -913,6 +915,8 @@ MUTEX_PROF_ARENA_MUTEXES
|
||||
&astats->astats.ndalloc_large);
|
||||
ctl_accum_arena_stats_u64(&sdstats->astats.nrequests_large,
|
||||
&astats->astats.nrequests_large);
|
||||
accum_atomic_zu(&sdstats->astats.abandoned_vm,
|
||||
&astats->astats.abandoned_vm);
|
||||
|
||||
accum_atomic_zu(&sdstats->astats.tcache_bytes,
|
||||
&astats->astats.tcache_bytes);
|
||||
@ -2871,6 +2875,9 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_tcache_bytes,
|
||||
CTL_RO_CGEN(config_stats, stats_arenas_i_resident,
|
||||
atomic_load_zu(&arenas_i(mib[2])->astats->astats.resident, ATOMIC_RELAXED),
|
||||
size_t)
|
||||
CTL_RO_CGEN(config_stats, stats_arenas_i_abandoned_vm,
|
||||
atomic_load_zu(&arenas_i(mib[2])->astats->astats.abandoned_vm,
|
||||
ATOMIC_RELAXED), size_t)
|
||||
|
||||
CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
|
||||
arenas_i(mib[2])->astats->allocated_small, size_t)
|
||||
|
16
src/extent.c
16
src/extent.c
@ -619,16 +619,24 @@ label_return:
|
||||
return extent;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can only happen when we fail to allocate a new extent struct (which
|
||||
* indicates OOM), e.g. when trying to split an existing extent.
|
||||
*/
|
||||
static void
|
||||
extents_leak(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
|
||||
extents_abandon_vm(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
|
||||
extents_t *extents, extent_t *extent, bool growing_retained) {
|
||||
size_t sz = extent_size_get(extent);
|
||||
if (config_stats) {
|
||||
arena_stats_accum_zu(&arena->stats.abandoned_vm, sz);
|
||||
}
|
||||
/*
|
||||
* Leak extent after making sure its pages have already been purged, so
|
||||
* that this is only a virtual memory leak.
|
||||
*/
|
||||
if (extents_state_get(extents) == extent_state_dirty) {
|
||||
if (extent_purge_lazy_impl(tsdn, arena, r_extent_hooks,
|
||||
extent, 0, extent_size_get(extent), growing_retained)) {
|
||||
extent, 0, sz, growing_retained)) {
|
||||
extent_purge_forced_impl(tsdn, arena, r_extent_hooks,
|
||||
extent, 0, extent_size_get(extent),
|
||||
growing_retained);
|
||||
@ -1083,7 +1091,7 @@ extent_recycle_split(tsdn_t *tsdn, arena_t *arena,
|
||||
if (to_leak != NULL) {
|
||||
void *leak = extent_base_get(to_leak);
|
||||
extent_deregister_no_gdump_sub(tsdn, to_leak);
|
||||
extents_leak(tsdn, arena, r_extent_hooks, extents,
|
||||
extents_abandon_vm(tsdn, arena, r_extent_hooks, extents,
|
||||
to_leak, growing_retained);
|
||||
assert(extent_lock_from_addr(tsdn, rtree_ctx, leak,
|
||||
false) == NULL);
|
||||
@ -1382,7 +1390,7 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena,
|
||||
}
|
||||
if (to_leak != NULL) {
|
||||
extent_deregister_no_gdump_sub(tsdn, to_leak);
|
||||
extents_leak(tsdn, arena, r_extent_hooks,
|
||||
extents_abandon_vm(tsdn, arena, r_extent_hooks,
|
||||
&arena->extents_retained, to_leak, true);
|
||||
}
|
||||
goto label_err;
|
||||
|
@ -673,7 +673,7 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||
size_t large_allocated;
|
||||
uint64_t large_nmalloc, large_ndalloc, large_nrequests, large_nfills,
|
||||
large_nflushes;
|
||||
size_t tcache_bytes;
|
||||
size_t tcache_bytes, abandoned_vm;
|
||||
uint64_t uptime;
|
||||
|
||||
CTL_GET("arenas.page", &page, size_t);
|
||||
@ -963,6 +963,7 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||
GET_AND_EMIT_MEM_STAT(metadata_thp)
|
||||
GET_AND_EMIT_MEM_STAT(tcache_bytes)
|
||||
GET_AND_EMIT_MEM_STAT(resident)
|
||||
GET_AND_EMIT_MEM_STAT(abandoned_vm)
|
||||
GET_AND_EMIT_MEM_STAT(extent_avail)
|
||||
#undef GET_AND_EMIT_MEM_STAT
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user