Add merged arena stats printing.

Add the "m" and "a" opts flags for malloc_stats_print().
This commit is contained in:
Jason Evans 2010-01-17 17:35:19 -08:00
parent 3363a841ca
commit b34e8684ec
4 changed files with 260 additions and 116 deletions

View File

@ -194,7 +194,11 @@ during execution can be omitted by specifying
as a character within the as a character within the
.Fa opts .Fa opts
string. string.
@roff_stats@Similarly, @roff_stats@.Dq m
@roff_stats@and
@roff_stats@.Dq a
@roff_stats@can be specified to omit merged arena and per arena statistics,
@roff_stats@respectively.
@roff_stats@.Dq b @roff_stats@.Dq b
@roff_stats@and @roff_stats@and
@roff_stats@.Dq l @roff_stats@.Dq l

View File

@ -405,6 +405,13 @@ void arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
arena_chunk_map_t *mapelm); arena_chunk_map_t *mapelm);
void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr); void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr);
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
void arena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty,
arena_stats_t *astats, malloc_bin_stats_t *bstats,
malloc_large_stats_t *lstats);
void arena_stats_mprint(arena_t *arena, size_t nactive, size_t ndirty,
const arena_stats_t *astats, const malloc_bin_stats_t *bstats,
const malloc_large_stats_t *lstats, bool bins, bool large,
void (*write4)(const char *, const char *, const char *, const char *));
void arena_stats_print(arena_t *arena, bool bins, bool large, void arena_stats_print(arena_t *arena, bool bins, bool large,
void (*write4)(const char *, const char *, const char *, const char *)); void (*write4)(const char *, const char *, const char *, const char *));
#endif #endif

View File

@ -172,6 +172,16 @@ static void *arena_malloc_large(arena_t *arena, size_t size, bool zero);
static bool arena_is_large(const void *ptr); static bool arena_is_large(const void *ptr);
static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,
arena_run_t *run, arena_bin_t *bin); arena_run_t *run, arena_bin_t *bin);
#ifdef JEMALLOC_STATS
static void arena_stats_aprint(size_t nactive, size_t ndirty,
const arena_stats_t *astats,
void (*write4)(const char *, const char *, const char *, const char *));
static void arena_stats_bprint(arena_t *arena,
const malloc_bin_stats_t *bstats,
void (*write4)(const char *, const char *, const char *, const char *));
static void arena_stats_lprint(const malloc_large_stats_t *lstats,
void (*write4)(const char *, const char *, const char *, const char *));
#endif
static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
void *ptr, size_t size, size_t oldsize); void *ptr, size_t size, size_t oldsize);
static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
@ -1548,40 +1558,88 @@ arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
void void
arena_stats_print(arena_t *arena, bool bins, bool large, arena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty,
arena_stats_t *astats, malloc_bin_stats_t *bstats,
malloc_large_stats_t *lstats)
{
unsigned i, nlclasses;
*nactive += arena->nactive;
*ndirty += arena->ndirty;
astats->npurge += arena->stats.npurge;
astats->nmadvise += arena->stats.nmadvise;
astats->purged += arena->stats.purged;
astats->allocated_small += arena->stats.allocated_small;
astats->nmalloc_small += arena->stats.nmalloc_small;
astats->ndalloc_small += arena->stats.ndalloc_small;
astats->allocated_medium += arena->stats.allocated_medium;
astats->nmalloc_medium += arena->stats.nmalloc_medium;
astats->ndalloc_medium += arena->stats.ndalloc_medium;
astats->allocated_large += arena->stats.allocated_large;
astats->nmalloc_large += arena->stats.nmalloc_large;
astats->ndalloc_large += arena->stats.ndalloc_large;
for (i = 0; i < nbins; i++) {
bstats[i].nrequests += arena->bins[i].stats.nrequests;
#ifdef JEMALLOC_TCACHE
bstats[i].nfills += arena->bins[i].stats.nfills;
bstats[i].nflushes += arena->bins[i].stats.nflushes;
#endif
bstats[i].nruns += arena->bins[i].stats.nruns;
bstats[i].reruns += arena->bins[i].stats.reruns;
bstats[i].highruns += arena->bins[i].stats.highruns;
bstats[i].curruns += arena->bins[i].stats.curruns;
}
for (i = 0, nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT;
i < nlclasses;
i++) {
lstats[i].nrequests += arena->stats.lstats[i].nrequests;
lstats[i].highruns += arena->stats.lstats[i].highruns;
lstats[i].curruns += arena->stats.lstats[i].curruns;
}
}
static void
arena_stats_aprint(size_t nactive, size_t ndirty, const arena_stats_t *astats,
void (*write4)(const char *, const char *, const char *, const char *)) void (*write4)(const char *, const char *, const char *, const char *))
{ {
malloc_cprintf(write4, malloc_cprintf(write4,
"dirty pages: %zu:%zu active:dirty, %llu sweep%s," "dirty pages: %zu:%zu active:dirty, %llu sweep%s,"
" %llu madvise%s, %llu purged\n", " %llu madvise%s, %llu purged\n",
arena->nactive, arena->ndirty, nactive, ndirty,
arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s", astats->npurge, astats->npurge == 1 ? "" : "s",
arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s", astats->nmadvise, astats->nmadvise == 1 ? "" : "s",
arena->stats.purged); astats->purged);
malloc_cprintf(write4, malloc_cprintf(write4,
" allocated nmalloc ndalloc\n"); " allocated nmalloc ndalloc\n");
malloc_cprintf(write4, "small: %12zu %12llu %12llu\n", malloc_cprintf(write4, "small: %12zu %12llu %12llu\n",
arena->stats.allocated_small, arena->stats.nmalloc_small, astats->allocated_small, astats->nmalloc_small,
arena->stats.ndalloc_small); astats->ndalloc_small);
malloc_cprintf(write4, "medium: %12zu %12llu %12llu\n", malloc_cprintf(write4, "medium: %12zu %12llu %12llu\n",
arena->stats.allocated_medium, arena->stats.nmalloc_medium, astats->allocated_medium, astats->nmalloc_medium,
arena->stats.ndalloc_medium); astats->ndalloc_medium);
malloc_cprintf(write4, "large: %12zu %12llu %12llu\n", malloc_cprintf(write4, "large: %12zu %12llu %12llu\n",
arena->stats.allocated_large, arena->stats.nmalloc_large, astats->allocated_large, astats->nmalloc_large,
arena->stats.ndalloc_large); astats->ndalloc_large);
malloc_cprintf(write4, "total: %12zu %12llu %12llu\n", malloc_cprintf(write4, "total: %12zu %12llu %12llu\n",
arena->stats.allocated_small + arena->stats.allocated_medium + astats->allocated_small + astats->allocated_medium +
arena->stats.allocated_large, arena->stats.nmalloc_small + astats->allocated_large, astats->nmalloc_small +
arena->stats.nmalloc_medium + arena->stats.nmalloc_large, astats->nmalloc_medium + astats->nmalloc_large,
arena->stats.ndalloc_small + arena->stats.ndalloc_medium + astats->ndalloc_small + astats->ndalloc_medium +
arena->stats.ndalloc_large); astats->ndalloc_large);
malloc_cprintf(write4, "mapped: %12zu\n", arena->stats.mapped); malloc_cprintf(write4, "mapped: %12zu\n", astats->mapped);
}
if (bins && arena->stats.nmalloc_small + arena->stats.nmalloc_medium > static void
0) { arena_stats_bprint(arena_t *arena, const malloc_bin_stats_t *bstats,
void (*write4)(const char *, const char *, const char *, const char *))
{
unsigned i, gap_start; unsigned i, gap_start;
#ifdef JEMALLOC_TCACHE #ifdef JEMALLOC_TCACHE
malloc_cprintf(write4, malloc_cprintf(write4,
"bins: bin size regs pgs requests " "bins: bin size regs pgs requests "
@ -1592,16 +1650,13 @@ arena_stats_print(arena_t *arena, bool bins, bool large,
"newruns reruns maxruns curruns\n"); "newruns reruns maxruns curruns\n");
#endif #endif
for (i = 0, gap_start = UINT_MAX; i < nbins; i++) { for (i = 0, gap_start = UINT_MAX; i < nbins; i++) {
if (arena->bins[i].stats.nruns == 0) { if (bstats[i].nruns == 0) {
if (gap_start == UINT_MAX) if (gap_start == UINT_MAX)
gap_start = i; gap_start = i;
} else { } else {
if (gap_start != UINT_MAX) { if (gap_start != UINT_MAX) {
if (i > gap_start + 1) { if (i > gap_start + 1) {
/* /* Gap of more than one size class. */
* Gap of more than one size
* class.
*/
malloc_cprintf(write4, malloc_cprintf(write4,
"[%u..%u]\n", gap_start, "[%u..%u]\n", gap_start,
i - 1); i - 1);
@ -1626,15 +1681,15 @@ arena_stats_print(arena_t *arena, bool bins, bool large,
arena->bins[i].reg_size, arena->bins[i].reg_size,
arena->bins[i].nregs, arena->bins[i].nregs,
arena->bins[i].run_size >> PAGE_SHIFT, arena->bins[i].run_size >> PAGE_SHIFT,
arena->bins[i].stats.nrequests, bstats[i].nrequests,
#ifdef JEMALLOC_TCACHE #ifdef JEMALLOC_TCACHE
arena->bins[i].stats.nfills, bstats[i].nfills,
arena->bins[i].stats.nflushes, bstats[i].nflushes,
#endif #endif
arena->bins[i].stats.nruns, bstats[i].nruns,
arena->bins[i].stats.reruns, bstats[i].reruns,
arena->bins[i].stats.highruns, bstats[i].highruns,
arena->bins[i].stats.curruns); bstats[i].curruns);
} }
} }
if (gap_start != UINT_MAX) { if (gap_start != UINT_MAX) {
@ -1647,9 +1702,12 @@ arena_stats_print(arena_t *arena, bool bins, bool large,
malloc_cprintf(write4, "[%u]\n", gap_start); malloc_cprintf(write4, "[%u]\n", gap_start);
} }
} }
} }
if (large && arena->stats.nmalloc_large > 0) { static void
arena_stats_lprint(const malloc_large_stats_t *lstats,
void (*write4)(const char *, const char *, const char *, const char *))
{
size_t i; size_t i;
ssize_t gap_start; ssize_t gap_start;
size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT; size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT;
@ -1658,7 +1716,7 @@ arena_stats_print(arena_t *arena, bool bins, bool large,
"large: size pages nrequests maxruns curruns\n"); "large: size pages nrequests maxruns curruns\n");
for (i = 0, gap_start = -1; i < nlclasses; i++) { for (i = 0, gap_start = -1; i < nlclasses; i++) {
if (arena->stats.lstats[i].nrequests == 0) { if (lstats[i].nrequests == 0) {
if (gap_start == -1) if (gap_start == -1)
gap_start = i; gap_start = i;
} else { } else {
@ -1670,14 +1728,47 @@ arena_stats_print(arena_t *arena, bool bins, bool large,
malloc_cprintf(write4, malloc_cprintf(write4,
"%13zu %5zu %9llu %9zu %9zu\n", "%13zu %5zu %9llu %9zu %9zu\n",
(i+1) << PAGE_SHIFT, i+1, (i+1) << PAGE_SHIFT, i+1,
arena->stats.lstats[i].nrequests, lstats[i].nrequests,
arena->stats.lstats[i].highruns, lstats[i].highruns,
arena->stats.lstats[i].curruns); lstats[i].curruns);
} }
} }
if (gap_start != -1) if (gap_start != -1)
malloc_cprintf(write4, "[%zu]\n", i - gap_start); malloc_cprintf(write4, "[%zu]\n", i - gap_start);
} }
void
arena_stats_mprint(arena_t *arena, size_t nactive, size_t ndirty,
const arena_stats_t *astats, const malloc_bin_stats_t *bstats,
const malloc_large_stats_t *lstats, bool bins, bool large,
void (*write4)(const char *, const char *, const char *, const char *))
{
arena_stats_aprint(nactive, ndirty, astats, write4);
if (bins && astats->nmalloc_small + astats->nmalloc_medium > 0)
arena_stats_bprint(arena, bstats, write4);
if (large && astats->nmalloc_large > 0)
arena_stats_lprint(lstats, write4);
}
void
arena_stats_print(arena_t *arena, bool bins, bool large,
void (*write4)(const char *, const char *, const char *, const char *))
{
size_t nactive, ndirty;
arena_stats_t astats;
malloc_bin_stats_t bstats[nbins];
malloc_large_stats_t lstats[((chunksize - PAGE_SIZE) >> PAGE_SHIFT)];
nactive = 0;
ndirty = 0;
memset(&astats, 0, sizeof(astats));
memset(bstats, 0, sizeof(bstats));
memset(lstats, 0, sizeof(lstats));
arena_stats_merge(arena, &nactive, &ndirty, &astats, bstats, lstats);
arena_stats_mprint(arena, nactive, ndirty, &astats, bstats, lstats,
bins, large, write4);
} }
#endif #endif

View File

@ -113,6 +113,8 @@ JEMALLOC_P(malloc_stats_print)(void (*write4)(const char *, const char *,
{ {
char s[UMAX2S_BUFSIZE]; char s[UMAX2S_BUFSIZE];
bool general = true; bool general = true;
bool merged = true;
bool unmerged = true;
bool bins = true; bool bins = true;
bool large = true; bool large = true;
@ -133,6 +135,12 @@ JEMALLOC_P(malloc_stats_print)(void (*write4)(const char *, const char *,
case 'g': case 'g':
general = false; general = false;
break; break;
case 'm':
merged = false;
break;
case 'a':
unmerged = false;
break;
case 'b': case 'b':
bins = false; bins = false;
break; break;
@ -279,17 +287,51 @@ JEMALLOC_P(malloc_stats_print)(void (*write4)(const char *, const char *,
malloc_cprintf(write4, " %12llu %12llu %12zu\n", huge_nmalloc, malloc_cprintf(write4, " %12llu %12llu %12zu\n", huge_nmalloc,
huge_ndalloc, huge_allocated); huge_ndalloc, huge_allocated);
if (merged) {
size_t nactive, ndirty;
arena_stats_t astats;
malloc_bin_stats_t bstats[nbins];
malloc_large_stats_t lstats[((chunksize - PAGE_SIZE) >>
PAGE_SHIFT)];
nactive = 0;
ndirty = 0;
memset(&astats, 0, sizeof(astats));
memset(bstats, 0, sizeof(bstats));
memset(lstats, 0, sizeof(lstats));
/* Create merged arena stats. */
for (i = 0; i < narenas; i++) {
arena = arenas[i];
if (arena != NULL) {
malloc_mutex_lock(&arena->lock);
arena_stats_merge(arena, &nactive,
&ndirty, &astats, bstats, lstats);
malloc_mutex_unlock(&arena->lock);
}
}
/* Print merged arena stats. */
malloc_cprintf(write4, "\nMerge arenas stats:\n");
/* arenas[0] is used only for invariant bin settings. */
arena_stats_mprint(arenas[0], nactive, ndirty, &astats,
bstats, lstats, bins, large, write4);
}
if (unmerged) {
/* Print stats for each arena. */ /* Print stats for each arena. */
for (i = 0; i < narenas; i++) { for (i = 0; i < narenas; i++) {
arena = arenas[i]; arena = arenas[i];
if (arena != NULL) { if (arena != NULL) {
malloc_cprintf(write4, "\narenas[%u]:\n", i); malloc_cprintf(write4,
"\narenas[%u]:\n", i);
malloc_mutex_lock(&arena->lock); malloc_mutex_lock(&arena->lock);
arena_stats_print(arena, bins, large, write4); arena_stats_print(arena, bins, large,
write4);
malloc_mutex_unlock(&arena->lock); malloc_mutex_unlock(&arena->lock);
} }
} }
} }
}
#endif /* #ifdef JEMALLOC_STATS */ #endif /* #ifdef JEMALLOC_STATS */
write4("--- End jemalloc statistics ---\n", "", "", ""); write4("--- End jemalloc statistics ---\n", "", "", "");
} }