server-skynet-source-3rd-je.../jemalloc/src/jemalloc_stats.c

296 lines
7.5 KiB
C
Raw Normal View History

#define JEMALLOC_STATS_C_
#include "internal/jemalloc_internal.h"
/******************************************************************************/
/* Data. */
bool opt_stats_print = false;
/******************************************************************************/
/* Function prototypes for non-inline static functions. */
static void
malloc_vcprintf(void (*write4)(const char *, const char *, const char *,
const char *), const char *format, va_list ap);
/******************************************************************************/
/*
* We don't want to depend on vsnprintf() for production builds, since that can
* cause unnecessary bloat for static binaries. umax2s() provides minimal
* integer printing functionality, so that malloc_printf() use can be limited to
* JEMALLOC_STATS code.
*/
char *
umax2s(uintmax_t x, unsigned base, char *s)
{
unsigned i;
i = UMAX2S_BUFSIZE - 1;
s[i] = '\0';
switch (base) {
case 10:
do {
i--;
s[i] = "0123456789"[x % 10];
x /= 10;
} while (x > 0);
break;
case 16:
do {
i--;
s[i] = "0123456789abcdef"[x & 0xf];
x >>= 4;
} while (x > 0);
break;
default:
do {
i--;
s[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % base];
x /= base;
} while (x > 0);
}
return (&s[i]);
}
#ifdef JEMALLOC_STATS
static void
malloc_vcprintf(void (*write4)(const char *, const char *, const char *,
const char *), const char *format, va_list ap)
{
char buf[4096];
if (write4 == NULL) {
/*
* The caller did not provide an alternate write4 callback
* function, so use the default one. malloc_write4() is an
* inline function, so use malloc_message() directly here.
*/
write4 = JEMALLOC_P(malloc_message);
}
vsnprintf(buf, sizeof(buf), format, ap);
write4(buf, "", "", "");
}
/*
* Print to a callback function in such a way as to (hopefully) avoid memory
* allocation.
*/
JEMALLOC_ATTR(format(printf, 2, 3))
void
malloc_cprintf(void (*write4)(const char *, const char *, const char *,
const char *), const char *format, ...)
{
va_list ap;
va_start(ap, format);
malloc_vcprintf(write4, format, ap);
va_end(ap);
}
/*
* Print to stderr in such a way as to (hopefully) avoid memory allocation.
*/
JEMALLOC_ATTR(format(printf, 1, 2))
void
malloc_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
malloc_vcprintf(NULL, format, ap);
va_end(ap);
}
#endif
JEMALLOC_ATTR(visibility("default"))
void
JEMALLOC_P(malloc_stats_print)(void (*write4)(const char *, const char *,
const char *, const char *), const char *opts)
{
char s[UMAX2S_BUFSIZE];
bool general = true;
bool bins = true;
bool large = true;
if (write4 == NULL) {
/*
* The caller did not provide an alternate write4 callback
* function, so use the default one. malloc_write4() is an
* inline function, so use malloc_message() directly here.
*/
write4 = JEMALLOC_P(malloc_message);
}
if (opts != NULL) {
unsigned i;
for (i = 0; opts[i] != '\0'; i++) {
switch (opts[i]) {
case 'g':
general = false;
break;
case 'b':
bins = false;
break;
case 'l':
large = false;
break;
default:;
}
}
}
write4("___ Begin jemalloc statistics ___\n", "", "", "");
if (general) {
write4("Assertions ",
#ifdef NDEBUG
"disabled",
#else
"enabled",
#endif
"\n", "");
write4("Boolean JEMALLOC_OPTIONS: ", opt_abort ? "A" : "a",
"", "");
#ifdef JEMALLOC_FILL
write4(opt_junk ? "J" : "j", "", "", "");
#endif
write4("P", "", "", "");
#ifdef JEMALLOC_TCACHE
write4(opt_tcache_sort ? "S" : "s", "", "", "");
#endif
#ifdef JEMALLOC_TRACE
write4(opt_trace ? "T" : "t", "", "", "");
#endif
#ifdef JEMALLOC_SYSV
write4(opt_sysv ? "V" : "v", "", "", "");
#endif
#ifdef JEMALLOC_XMALLOC
write4(opt_xmalloc ? "X" : "x", "", "", "");
#endif
#ifdef JEMALLOC_FILL
write4(opt_zero ? "Z" : "z", "", "", "");
#endif
write4("\n", "", "", "");
write4("CPUs: ", umax2s(ncpus, 10, s), "\n", "");
write4("Max arenas: ", umax2s(narenas, 10, s), "\n", "");
write4("Pointer size: ", umax2s(sizeof(void *), 10, s), "\n",
"");
write4("Quantum size: ", umax2s(QUANTUM, 10, s), "\n", "");
write4("Cacheline size (assumed): ", umax2s(CACHELINE, 10, s),
"\n", "");
write4("Subpage spacing: ", umax2s(SUBPAGE, 10, s), "\n", "");
write4("Medium spacing: ", umax2s((1U << lg_mspace), 10, s),
"\n", "");
#ifdef JEMALLOC_TINY
write4("Tiny 2^n-spaced sizes: [", umax2s((1U << LG_TINY_MIN),
10, s), "..", "");
write4(umax2s((qspace_min >> 1), 10, s), "]\n", "", "");
#endif
write4("Quantum-spaced sizes: [", umax2s(qspace_min, 10, s),
"..", "");
write4(umax2s(qspace_max, 10, s), "]\n", "", "");
write4("Cacheline-spaced sizes: [", umax2s(cspace_min, 10, s),
"..", "");
write4(umax2s(cspace_max, 10, s), "]\n", "", "");
write4("Subpage-spaced sizes: [", umax2s(sspace_min, 10, s),
"..", "");
write4(umax2s(sspace_max, 10, s), "]\n", "", "");
write4("Medium sizes: [", umax2s(medium_min, 10, s), "..", "");
write4(umax2s(medium_max, 10, s), "]\n", "", "");
if (opt_lg_dirty_mult >= 0) {
write4("Min active:dirty page ratio per arena: ",
umax2s((1U << opt_lg_dirty_mult), 10, s), ":1\n",
"");
} else {
write4("Min active:dirty page ratio per arena: N/A\n",
"", "", "");
}
#ifdef JEMALLOC_TCACHE
write4("Thread cache slots per size class: ",
tcache_nslots ? umax2s(tcache_nslots, 10, s) : "N/A", "\n",
"");
write4("Thread cache GC sweep interval: ",
(tcache_nslots && tcache_gc_incr > 0) ?
umax2s((1U << opt_lg_tcache_gc_sweep), 10, s) : "N/A",
"", "");
write4(" (increment interval: ",
(tcache_nslots && tcache_gc_incr > 0) ?
umax2s(tcache_gc_incr, 10, s) : "N/A",
")\n", "");
#endif
write4("Chunk size: ", umax2s(chunksize, 10, s), "", "");
write4(" (2^", umax2s(opt_lg_chunk, 10, s), ")\n", "");
}
#ifdef JEMALLOC_STATS
{
size_t allocated, mapped;
unsigned i;
arena_t *arena;
/* Calculate and print allocated/mapped stats. */
/* arenas. */
for (i = 0, allocated = 0; i < narenas; i++) {
if (arenas[i] != NULL) {
malloc_mutex_lock(&arenas[i]->lock);
allocated += arenas[i]->stats.allocated_small;
allocated += arenas[i]->stats.allocated_large;
malloc_mutex_unlock(&arenas[i]->lock);
}
}
/* huge/base. */
malloc_mutex_lock(&huge_mtx);
allocated += huge_allocated;
mapped = stats_chunks.curchunks * chunksize;
malloc_mutex_unlock(&huge_mtx);
malloc_mutex_lock(&base_mtx);
mapped += base_mapped;
malloc_mutex_unlock(&base_mtx);
malloc_cprintf(write4, "Allocated: %zu, mapped: %zu\n",
allocated, mapped);
/* Print chunk stats. */
{
chunk_stats_t chunks_stats;
malloc_mutex_lock(&huge_mtx);
chunks_stats = stats_chunks;
malloc_mutex_unlock(&huge_mtx);
malloc_cprintf(write4, "chunks: nchunks "
"highchunks curchunks\n");
malloc_cprintf(write4, " %13llu%13lu%13lu\n",
chunks_stats.nchunks, chunks_stats.highchunks,
chunks_stats.curchunks);
}
/* Print chunk stats. */
malloc_cprintf(write4,
"huge: nmalloc ndalloc allocated\n");
malloc_cprintf(write4, " %12llu %12llu %12zu\n", huge_nmalloc,
huge_ndalloc, huge_allocated);
/* Print stats for each arena. */
for (i = 0; i < narenas; i++) {
arena = arenas[i];
if (arena != NULL) {
malloc_cprintf(write4, "\narenas[%u]:\n", i);
malloc_mutex_lock(&arena->lock);
arena_stats_print(arena, bins, large, write4);
malloc_mutex_unlock(&arena->lock);
}
}
}
#endif /* #ifdef JEMALLOC_STATS */
write4("--- End jemalloc statistics ---\n", "", "", "");
}