]> git.saurik.com Git - redis.git/blobdiff - deps/jemalloc/src/stats.c
Jemalloc updated to 3.0.0.
[redis.git] / deps / jemalloc / src / stats.c
index cbbbb5ba6dcd22edc2e49a01c22fb72b06a9b6d4..433b80d128d9f05c01824adece7a0a3d8dd3899d 100644 (file)
 
 bool   opt_stats_print = false;
 
-#ifdef JEMALLOC_STATS
 size_t stats_cactive = 0;
-#endif
 
 /******************************************************************************/
 /* Function prototypes for non-inline static functions. */
 
-#ifdef JEMALLOC_STATS
-static void    malloc_vcprintf(void (*write_cb)(void *, const char *),
-    void *cbopaque, const char *format, va_list ap);
 static void    stats_arena_bins_print(void (*write_cb)(void *, const char *),
     void *cbopaque, unsigned i);
 static void    stats_arena_lruns_print(void (*write_cb)(void *, const char *),
     void *cbopaque, unsigned i);
 static void    stats_arena_print(void (*write_cb)(void *, const char *),
-    void *cbopaque, unsigned i);
-#endif
+    void *cbopaque, unsigned i, bool bins, bool large);
 
 /******************************************************************************/
 
-/*
- * We don't want to depend on vsnprintf() for production builds, since that can
- * cause unnecessary bloat for static binaries.  u2s() provides minimal integer
- * printing functionality, so that malloc_printf() use can be limited to
- * JEMALLOC_STATS code.
- */
-char *
-u2s(uint64_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 % (uint64_t)10];
-                       x /= (uint64_t)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 %
-                           (uint64_t)base];
-                       x /= (uint64_t)base;
-               } while (x > 0);
-       }
-
-       return (&s[i]);
-}
-
-#ifdef JEMALLOC_STATS
-static void
-malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
-    const char *format, va_list ap)
-{
-       char buf[4096];
-
-       if (write_cb == NULL) {
-               /*
-                * The caller did not provide an alternate write_cb callback
-                * function, so use the default one.  malloc_write() is an
-                * inline function, so use malloc_message() directly here.
-                */
-               write_cb = JEMALLOC_P(malloc_message);
-               cbopaque = NULL;
-       }
-
-       vsnprintf(buf, sizeof(buf), format, ap);
-       write_cb(cbopaque, buf);
-}
-
-/*
- * Print to a callback function in such a way as to (hopefully) avoid memory
- * allocation.
- */
-JEMALLOC_ATTR(format(printf, 3, 4))
-void
-malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,
-    const char *format, ...)
-{
-       va_list ap;
-
-       va_start(ap, format);
-       malloc_vcprintf(write_cb, cbopaque, 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, NULL, format, ap);
-       va_end(ap);
-}
-#endif
-
-#ifdef JEMALLOC_STATS
 static void
 stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
     unsigned i)
 {
-       size_t pagesize;
+       size_t page;
        bool config_tcache;
        unsigned nbins, j, gap_start;
 
-       CTL_GET("arenas.pagesize", &pagesize, size_t);
+       CTL_GET("arenas.page", &page, size_t);
 
        CTL_GET("config.tcache", &config_tcache, bool);
        if (config_tcache) {
                malloc_cprintf(write_cb, cbopaque,
-                   "bins:     bin    size regs pgs    allocated      nmalloc"
+                   "bins:     bin  size regs pgs    allocated      nmalloc"
                    "      ndalloc    nrequests       nfills     nflushes"
-                   "      newruns       reruns      maxruns      curruns\n");
+                   "      newruns       reruns      curruns\n");
        } else {
                malloc_cprintf(write_cb, cbopaque,
-                   "bins:     bin    size regs pgs    allocated      nmalloc"
-                   "      ndalloc      newruns       reruns      maxruns"
-                   "      curruns\n");
+                   "bins:     bin  size regs pgs    allocated      nmalloc"
+                   "      ndalloc      newruns       reruns      curruns\n");
        }
        CTL_GET("arenas.nbins", &nbins, unsigned);
        for (j = 0, gap_start = UINT_MAX; j < nbins; j++) {
@@ -183,12 +83,11 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
                        if (gap_start == UINT_MAX)
                                gap_start = j;
                } else {
-                       unsigned ntbins_, nqbins, ncbins, nsbins;
                        size_t reg_size, run_size, allocated;
                        uint32_t nregs;
                        uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
                        uint64_t reruns;
-                       size_t highruns, curruns;
+                       size_t curruns;
 
                        if (gap_start != UINT_MAX) {
                                if (j > gap_start + 1) {
@@ -203,10 +102,6 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
                                }
                                gap_start = UINT_MAX;
                        }
-                       CTL_GET("arenas.ntbins", &ntbins_, unsigned);
-                       CTL_GET("arenas.nqbins", &nqbins, unsigned);
-                       CTL_GET("arenas.ncbins", &ncbins, unsigned);
-                       CTL_GET("arenas.nsbins", &nsbins, unsigned);
                        CTL_J_GET("arenas.bin.0.size", &reg_size, size_t);
                        CTL_J_GET("arenas.bin.0.nregs", &nregs, uint32_t);
                        CTL_J_GET("arenas.bin.0.run_size", &run_size, size_t);
@@ -226,36 +121,25 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
                        }
                        CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns,
                            uint64_t);
-                       CTL_IJ_GET("stats.arenas.0.bins.0.highruns", &highruns,
-                           size_t);
                        CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns,
                            size_t);
                        if (config_tcache) {
                                malloc_cprintf(write_cb, cbopaque,
-                                   "%13u %1s %5zu %4u %3zu %12zu %12"PRIu64
+                                   "%13u %5zu %4u %3zu %12zu %12"PRIu64
                                    " %12"PRIu64" %12"PRIu64" %12"PRIu64
                                    " %12"PRIu64" %12"PRIu64" %12"PRIu64
-                                   " %12zu %12zu\n",
-                                   j,
-                                   j < ntbins_ ? "T" : j < ntbins_ + nqbins ?
-                                   "Q" : j < ntbins_ + nqbins + ncbins ? "C" :
-                                   "S",
-                                   reg_size, nregs, run_size / pagesize,
+                                   " %12zu\n",
+                                   j, reg_size, nregs, run_size / page,
                                    allocated, nmalloc, ndalloc, nrequests,
-                                   nfills, nflushes, nruns, reruns, highruns,
-                                   curruns);
+                                   nfills, nflushes, nruns, reruns, curruns);
                        } else {
                                malloc_cprintf(write_cb, cbopaque,
-                                   "%13u %1s %5zu %4u %3zu %12zu %12"PRIu64
+                                   "%13u %5zu %4u %3zu %12zu %12"PRIu64
                                    " %12"PRIu64" %12"PRIu64" %12"PRIu64
-                                   " %12zu %12zu\n",
-                                   j,
-                                   j < ntbins_ ? "T" : j < ntbins_ + nqbins ?
-                                   "Q" : j < ntbins_ + nqbins + ncbins ? "C" :
-                                   "S",
-                                   reg_size, nregs, run_size / pagesize,
+                                   " %12zu\n",
+                                   j, reg_size, nregs, run_size / page,
                                    allocated, nmalloc, ndalloc, nruns, reruns,
-                                   highruns, curruns);
+                                   curruns);
                        }
                }
        }
@@ -275,18 +159,18 @@ static void
 stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
     unsigned i)
 {
-       size_t pagesize, nlruns, j;
+       size_t page, nlruns, j;
        ssize_t gap_start;
 
-       CTL_GET("arenas.pagesize", &pagesize, size_t);
+       CTL_GET("arenas.page", &page, size_t);
 
        malloc_cprintf(write_cb, cbopaque,
            "large:   size pages      nmalloc      ndalloc    nrequests"
-           "      maxruns      curruns\n");
+           "      curruns\n");
        CTL_GET("arenas.nlruns", &nlruns, size_t);
        for (j = 0, gap_start = -1; j < nlruns; j++) {
                uint64_t nmalloc, ndalloc, nrequests;
-               size_t run_size, highruns, curruns;
+               size_t run_size, curruns;
 
                CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc,
                    uint64_t);
@@ -299,8 +183,6 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
                                gap_start = j;
                } else {
                        CTL_J_GET("arenas.lrun.0.size", &run_size, size_t);
-                       CTL_IJ_GET("stats.arenas.0.lruns.0.highruns", &highruns,
-                           size_t);
                        CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns,
                            size_t);
                        if (gap_start != -1) {
@@ -310,9 +192,9 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
                        }
                        malloc_cprintf(write_cb, cbopaque,
                            "%13zu %5zu %12"PRIu64" %12"PRIu64" %12"PRIu64
-                           " %12zu %12zu\n",
-                           run_size, run_size / pagesize, nmalloc, ndalloc,
-                           nrequests, highruns, curruns);
+                           " %12zu\n",
+                           run_size, run_size / page, nmalloc, ndalloc,
+                           nrequests, curruns);
                }
        }
        if (gap_start != -1)
@@ -321,17 +203,17 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
 
 static void
 stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
-    unsigned i)
+    unsigned i, bool bins, bool large)
 {
        unsigned nthreads;
-       size_t pagesize, pactive, pdirty, mapped;
+       size_t page, pactive, pdirty, mapped;
        uint64_t npurge, nmadvise, purged;
        size_t small_allocated;
        uint64_t small_nmalloc, small_ndalloc, small_nrequests;
        size_t large_allocated;
        uint64_t large_nmalloc, large_ndalloc, large_nrequests;
 
-       CTL_GET("arenas.pagesize", &pagesize, size_t);
+       CTL_GET("arenas.page", &page, size_t);
 
        CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned);
        malloc_cprintf(write_cb, cbopaque,
@@ -369,15 +251,15 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
            small_nmalloc + large_nmalloc,
            small_ndalloc + large_ndalloc,
            small_nrequests + large_nrequests);
-       malloc_cprintf(write_cb, cbopaque, "active:  %12zu\n",
-           pactive * pagesize );
+       malloc_cprintf(write_cb, cbopaque, "active:  %12zu\n", pactive * page);
        CTL_I_GET("stats.arenas.0.mapped", &mapped, size_t);
        malloc_cprintf(write_cb, cbopaque, "mapped:  %12zu\n", mapped);
 
-       stats_arena_bins_print(write_cb, cbopaque, i);
-       stats_arena_lruns_print(write_cb, cbopaque, i);
+       if (bins)
+               stats_arena_bins_print(write_cb, cbopaque, i);
+       if (large)
+               stats_arena_lruns_print(write_cb, cbopaque, i);
 }
-#endif
 
 void
 stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
@@ -386,7 +268,6 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
        int err;
        uint64_t epoch;
        size_t u64sz;
-       char s[UMAX2S_BUFSIZE];
        bool general = true;
        bool merged = true;
        bool unmerged = true;
@@ -402,8 +283,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
         * */
        epoch = 1;
        u64sz = sizeof(uint64_t);
-       err = JEMALLOC_P(mallctl)("epoch", &epoch, &u64sz, &epoch,
-           sizeof(uint64_t));
+       err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t));
        if (err != 0) {
                if (err == EAGAIN) {
                        malloc_write("<jemalloc>: Memory allocation failure in "
@@ -415,42 +295,33 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
                abort();
        }
 
-       if (write_cb == NULL) {
-               /*
-                * The caller did not provide an alternate write_cb callback
-                * function, so use the default one.  malloc_write() is an
-                * inline function, so use malloc_message() directly here.
-                */
-               write_cb = JEMALLOC_P(malloc_message);
-               cbopaque = NULL;
-       }
-
        if (opts != NULL) {
                unsigned i;
 
                for (i = 0; opts[i] != '\0'; i++) {
                        switch (opts[i]) {
-                               case 'g':
-                                       general = false;
-                                       break;
-                               case 'm':
-                                       merged = false;
-                                       break;
-                               case 'a':
-                                       unmerged = false;
-                                       break;
-                               case 'b':
-                                       bins = false;
-                                       break;
-                               case 'l':
-                                       large = false;
-                                       break;
-                               default:;
+                       case 'g':
+                               general = false;
+                               break;
+                       case 'm':
+                               merged = false;
+                               break;
+                       case 'a':
+                               unmerged = false;
+                               break;
+                       case 'b':
+                               bins = false;
+                               break;
+                       case 'l':
+                               large = false;
+                               break;
+                       default:;
                        }
                }
        }
 
-       write_cb(cbopaque, "___ Begin jemalloc statistics ___\n");
+       malloc_cprintf(write_cb, cbopaque,
+           "___ Begin jemalloc statistics ___\n");
        if (general) {
                int err;
                const char *cpv;
@@ -465,229 +336,126 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
                cpsz = sizeof(const char *);
 
                CTL_GET("version", &cpv, const char *);
-               write_cb(cbopaque, "Version: ");
-               write_cb(cbopaque, cpv);
-               write_cb(cbopaque, "\n");
+               malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv);
                CTL_GET("config.debug", &bv, bool);
-               write_cb(cbopaque, "Assertions ");
-               write_cb(cbopaque, bv ? "enabled" : "disabled");
-               write_cb(cbopaque, "\n");
+               malloc_cprintf(write_cb, cbopaque, "Assertions %s\n",
+                   bv ? "enabled" : "disabled");
 
 #define OPT_WRITE_BOOL(n)                                              \
-               if ((err = JEMALLOC_P(mallctl)("opt."#n, &bv, &bsz,     \
-                   NULL, 0)) == 0) {                                   \
-                       write_cb(cbopaque, "  opt."#n": ");             \
-                       write_cb(cbopaque, bv ? "true" : "false");      \
-                       write_cb(cbopaque, "\n");                       \
+               if ((err = je_mallctl("opt."#n, &bv, &bsz, NULL, 0))    \
+                   == 0) {                                             \
+                       malloc_cprintf(write_cb, cbopaque,              \
+                           "  opt."#n": %s\n", bv ? "true" : "false"); \
                }
 #define OPT_WRITE_SIZE_T(n)                                            \
-               if ((err = JEMALLOC_P(mallctl)("opt."#n, &sv, &ssz,     \
-                   NULL, 0)) == 0) {                                   \
-                       write_cb(cbopaque, "  opt."#n": ");             \
-                       write_cb(cbopaque, u2s(sv, 10, s));             \
-                       write_cb(cbopaque, "\n");                       \
+               if ((err = je_mallctl("opt."#n, &sv, &ssz, NULL, 0))    \
+                   == 0) {                                             \
+                       malloc_cprintf(write_cb, cbopaque,              \
+                       "  opt."#n": %zu\n", sv);                       \
                }
 #define OPT_WRITE_SSIZE_T(n)                                           \
-               if ((err = JEMALLOC_P(mallctl)("opt."#n, &ssv, &sssz,   \
-                   NULL, 0)) == 0) {                                   \
-                       if (ssv >= 0) {                                 \
-                               write_cb(cbopaque, "  opt."#n": ");     \
-                               write_cb(cbopaque, u2s(ssv, 10, s));    \
-                       } else {                                        \
-                               write_cb(cbopaque, "  opt."#n": -");    \
-                               write_cb(cbopaque, u2s(-ssv, 10, s));   \
-                       }                                               \
-                       write_cb(cbopaque, "\n");                       \
+               if ((err = je_mallctl("opt."#n, &ssv, &sssz, NULL, 0))  \
+                   == 0) {                                             \
+                       malloc_cprintf(write_cb, cbopaque,              \
+                           "  opt."#n": %zd\n", ssv);                  \
                }
 #define OPT_WRITE_CHAR_P(n)                                            \
-               if ((err = JEMALLOC_P(mallctl)("opt."#n, &cpv, &cpsz,   \
-                   NULL, 0)) == 0) {                                   \
-                       write_cb(cbopaque, "  opt."#n": \"");           \
-                       write_cb(cbopaque, cpv);                        \
-                       write_cb(cbopaque, "\"\n");                     \
+               if ((err = je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0))  \
+                   == 0) {                                             \
+                       malloc_cprintf(write_cb, cbopaque,              \
+                           "  opt."#n": \"%s\"\n", cpv);               \
                }
 
-               write_cb(cbopaque, "Run-time option settings:\n");
+               malloc_cprintf(write_cb, cbopaque,
+                   "Run-time option settings:\n");
                OPT_WRITE_BOOL(abort)
-               OPT_WRITE_SIZE_T(lg_qspace_max)
-               OPT_WRITE_SIZE_T(lg_cspace_max)
                OPT_WRITE_SIZE_T(lg_chunk)
                OPT_WRITE_SIZE_T(narenas)
                OPT_WRITE_SSIZE_T(lg_dirty_mult)
                OPT_WRITE_BOOL(stats_print)
                OPT_WRITE_BOOL(junk)
+               OPT_WRITE_SIZE_T(quarantine)
+               OPT_WRITE_BOOL(redzone)
                OPT_WRITE_BOOL(zero)
-               OPT_WRITE_BOOL(sysv)
+               OPT_WRITE_BOOL(utrace)
+               OPT_WRITE_BOOL(valgrind)
                OPT_WRITE_BOOL(xmalloc)
                OPT_WRITE_BOOL(tcache)
-               OPT_WRITE_SSIZE_T(lg_tcache_gc_sweep)
                OPT_WRITE_SSIZE_T(lg_tcache_max)
                OPT_WRITE_BOOL(prof)
                OPT_WRITE_CHAR_P(prof_prefix)
-               OPT_WRITE_SIZE_T(lg_prof_bt_max)
                OPT_WRITE_BOOL(prof_active)
                OPT_WRITE_SSIZE_T(lg_prof_sample)
                OPT_WRITE_BOOL(prof_accum)
-               OPT_WRITE_SSIZE_T(lg_prof_tcmax)
                OPT_WRITE_SSIZE_T(lg_prof_interval)
                OPT_WRITE_BOOL(prof_gdump)
+               OPT_WRITE_BOOL(prof_final)
                OPT_WRITE_BOOL(prof_leak)
-               OPT_WRITE_BOOL(overcommit)
 
 #undef OPT_WRITE_BOOL
 #undef OPT_WRITE_SIZE_T
 #undef OPT_WRITE_SSIZE_T
 #undef OPT_WRITE_CHAR_P
 
-               write_cb(cbopaque, "CPUs: ");
-               write_cb(cbopaque, u2s(ncpus, 10, s));
-               write_cb(cbopaque, "\n");
+               malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus);
 
                CTL_GET("arenas.narenas", &uv, unsigned);
-               write_cb(cbopaque, "Max arenas: ");
-               write_cb(cbopaque, u2s(uv, 10, s));
-               write_cb(cbopaque, "\n");
+               malloc_cprintf(write_cb, cbopaque, "Max arenas: %u\n", uv);
 
-               write_cb(cbopaque, "Pointer size: ");
-               write_cb(cbopaque, u2s(sizeof(void *), 10, s));
-               write_cb(cbopaque, "\n");
+               malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n",
+                   sizeof(void *));
 
                CTL_GET("arenas.quantum", &sv, size_t);
-               write_cb(cbopaque, "Quantum size: ");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "\n");
-
-               CTL_GET("arenas.cacheline", &sv, size_t);
-               write_cb(cbopaque, "Cacheline size (assumed): ");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "\n");
-
-               CTL_GET("arenas.subpage", &sv, size_t);
-               write_cb(cbopaque, "Subpage spacing: ");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "\n");
-
-               if ((err = JEMALLOC_P(mallctl)("arenas.tspace_min", &sv, &ssz,
-                   NULL, 0)) == 0) {
-                       write_cb(cbopaque, "Tiny 2^n-spaced sizes: [");
-                       write_cb(cbopaque, u2s(sv, 10, s));
-                       write_cb(cbopaque, "..");
-
-                       CTL_GET("arenas.tspace_max", &sv, size_t);
-                       write_cb(cbopaque, u2s(sv, 10, s));
-                       write_cb(cbopaque, "]\n");
-               }
+               malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv);
 
-               CTL_GET("arenas.qspace_min", &sv, size_t);
-               write_cb(cbopaque, "Quantum-spaced sizes: [");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "..");
-               CTL_GET("arenas.qspace_max", &sv, size_t);
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "]\n");
-
-               CTL_GET("arenas.cspace_min", &sv, size_t);
-               write_cb(cbopaque, "Cacheline-spaced sizes: [");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "..");
-               CTL_GET("arenas.cspace_max", &sv, size_t);
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "]\n");
-
-               CTL_GET("arenas.sspace_min", &sv, size_t);
-               write_cb(cbopaque, "Subpage-spaced sizes: [");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "..");
-               CTL_GET("arenas.sspace_max", &sv, size_t);
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, "]\n");
+               CTL_GET("arenas.page", &sv, size_t);
+               malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv);
 
                CTL_GET("opt.lg_dirty_mult", &ssv, ssize_t);
                if (ssv >= 0) {
-                       write_cb(cbopaque,
-                           "Min active:dirty page ratio per arena: ");
-                       write_cb(cbopaque, u2s((1U << ssv), 10, s));
-                       write_cb(cbopaque, ":1\n");
+                       malloc_cprintf(write_cb, cbopaque,
+                           "Min active:dirty page ratio per arena: %u:1\n",
+                           (1U << ssv));
                } else {
-                       write_cb(cbopaque,
+                       malloc_cprintf(write_cb, cbopaque,
                            "Min active:dirty page ratio per arena: N/A\n");
                }
-               if ((err = JEMALLOC_P(mallctl)("arenas.tcache_max", &sv,
-                   &ssz, NULL, 0)) == 0) {
-                       write_cb(cbopaque,
-                           "Maximum thread-cached size class: ");
-                       write_cb(cbopaque, u2s(sv, 10, s));
-                       write_cb(cbopaque, "\n");
-               }
-               if ((err = JEMALLOC_P(mallctl)("opt.lg_tcache_gc_sweep", &ssv,
-                   &ssz, NULL, 0)) == 0) {
-                       size_t tcache_gc_sweep = (1U << ssv);
-                       bool tcache_enabled;
-                       CTL_GET("opt.tcache", &tcache_enabled, bool);
-                       write_cb(cbopaque, "Thread cache GC sweep interval: ");
-                       write_cb(cbopaque, tcache_enabled && ssv >= 0 ?
-                           u2s(tcache_gc_sweep, 10, s) : "N/A");
-                       write_cb(cbopaque, "\n");
+               if ((err = je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0))
+                   == 0) {
+                       malloc_cprintf(write_cb, cbopaque,
+                           "Maximum thread-cached size class: %zu\n", sv);
                }
-               if ((err = JEMALLOC_P(mallctl)("opt.prof", &bv, &bsz, NULL, 0))
-                  == 0 && bv) {
-                       CTL_GET("opt.lg_prof_bt_max", &sv, size_t);
-                       write_cb(cbopaque, "Maximum profile backtrace depth: ");
-                       write_cb(cbopaque, u2s((1U << sv), 10, s));
-                       write_cb(cbopaque, "\n");
-
-                       CTL_GET("opt.lg_prof_tcmax", &ssv, ssize_t);
-                       write_cb(cbopaque,
-                           "Maximum per thread backtrace cache: ");
-                       if (ssv >= 0) {
-                               write_cb(cbopaque, u2s((1U << ssv), 10, s));
-                               write_cb(cbopaque, " (2^");
-                               write_cb(cbopaque, u2s(ssv, 10, s));
-                               write_cb(cbopaque, ")\n");
-                       } else
-                               write_cb(cbopaque, "N/A\n");
-
+               if ((err = je_mallctl("opt.prof", &bv, &bsz, NULL, 0)) == 0 &&
+                   bv) {
                        CTL_GET("opt.lg_prof_sample", &sv, size_t);
-                       write_cb(cbopaque, "Average profile sample interval: ");
-                       write_cb(cbopaque, u2s((((uint64_t)1U) << sv), 10, s));
-                       write_cb(cbopaque, " (2^");
-                       write_cb(cbopaque, u2s(sv, 10, s));
-                       write_cb(cbopaque, ")\n");
+                       malloc_cprintf(write_cb, cbopaque,
+                           "Average profile sample interval: %"PRIu64
+                           " (2^%zu)\n", (((uint64_t)1U) << sv), sv);
 
                        CTL_GET("opt.lg_prof_interval", &ssv, ssize_t);
-                       write_cb(cbopaque, "Average profile dump interval: ");
                        if (ssv >= 0) {
-                               write_cb(cbopaque, u2s((((uint64_t)1U) << ssv),
-                                   10, s));
-                               write_cb(cbopaque, " (2^");
-                               write_cb(cbopaque, u2s(ssv, 10, s));
-                               write_cb(cbopaque, ")\n");
-                       } else
-                               write_cb(cbopaque, "N/A\n");
+                               malloc_cprintf(write_cb, cbopaque,
+                                   "Average profile dump interval: %"PRIu64
+                                   " (2^%zd)\n",
+                                   (((uint64_t)1U) << ssv), ssv);
+                       } else {
+                               malloc_cprintf(write_cb, cbopaque,
+                                   "Average profile dump interval: N/A\n");
+                       }
                }
-               CTL_GET("arenas.chunksize", &sv, size_t);
-               write_cb(cbopaque, "Chunk size: ");
-               write_cb(cbopaque, u2s(sv, 10, s));
                CTL_GET("opt.lg_chunk", &sv, size_t);
-               write_cb(cbopaque, " (2^");
-               write_cb(cbopaque, u2s(sv, 10, s));
-               write_cb(cbopaque, ")\n");
+               malloc_cprintf(write_cb, cbopaque, "Chunk size: %zu (2^%zu)\n",
+                   (ZU(1) << sv), sv);
        }
 
-#ifdef JEMALLOC_STATS
-       {
-               int err;
-               size_t sszp, ssz;
+       if (config_stats) {
                size_t *cactive;
                size_t allocated, active, mapped;
-               size_t chunks_current, chunks_high, swap_avail;
+               size_t chunks_current, chunks_high;
                uint64_t chunks_total;
                size_t huge_allocated;
                uint64_t huge_nmalloc, huge_ndalloc;
 
-               sszp = sizeof(size_t *);
-               ssz = sizeof(size_t);
-
                CTL_GET("stats.cactive", &cactive, size_t *);
                CTL_GET("stats.allocated", &allocated, size_t);
                CTL_GET("stats.active", &active, size_t);
@@ -702,24 +470,10 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
                CTL_GET("stats.chunks.total", &chunks_total, uint64_t);
                CTL_GET("stats.chunks.high", &chunks_high, size_t);
                CTL_GET("stats.chunks.current", &chunks_current, size_t);
-               if ((err = JEMALLOC_P(mallctl)("swap.avail", &swap_avail, &ssz,
-                   NULL, 0)) == 0) {
-                       size_t lg_chunk;
-
-                       malloc_cprintf(write_cb, cbopaque, "chunks: nchunks   "
-                           "highchunks    curchunks   swap_avail\n");
-                       CTL_GET("opt.lg_chunk", &lg_chunk, size_t);
-                       malloc_cprintf(write_cb, cbopaque,
-                           "  %13"PRIu64"%13zu%13zu%13zu\n",
-                           chunks_total, chunks_high, chunks_current,
-                           swap_avail << lg_chunk);
-               } else {
-                       malloc_cprintf(write_cb, cbopaque, "chunks: nchunks   "
-                           "highchunks    curchunks\n");
-                       malloc_cprintf(write_cb, cbopaque,
-                           "  %13"PRIu64"%13zu%13zu\n",
-                           chunks_total, chunks_high, chunks_current);
-               }
+               malloc_cprintf(write_cb, cbopaque, "chunks: nchunks   "
+                   "highchunks    curchunks\n");
+               malloc_cprintf(write_cb, cbopaque, "  %13"PRIu64"%13zu%13zu\n",
+                   chunks_total, chunks_high, chunks_current);
 
                /* Print huge stats. */
                CTL_GET("stats.huge.nmalloc", &huge_nmalloc, uint64_t);
@@ -736,11 +490,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
 
                        CTL_GET("arenas.narenas", &narenas, unsigned);
                        {
-                               bool initialized[narenas];
+                               VARIABLE_ARRAY(bool, initialized, narenas);
                                size_t isz;
                                unsigned i, ninitialized;
 
-                               isz = sizeof(initialized);
+                               isz = sizeof(bool) * narenas;
                                xmallctl("arenas.initialized", initialized,
                                    &isz, NULL, 0);
                                for (i = ninitialized = 0; i < narenas; i++) {
@@ -748,12 +502,12 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
                                                ninitialized++;
                                }
 
-                               if (ninitialized > 1) {
+                               if (ninitialized > 1 || unmerged == false) {
                                        /* Print merged arena stats. */
                                        malloc_cprintf(write_cb, cbopaque,
                                            "\nMerged arenas stats:\n");
                                        stats_arena_print(write_cb, cbopaque,
-                                           narenas);
+                                           narenas, bins, large);
                                }
                        }
                }
@@ -765,11 +519,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
 
                        CTL_GET("arenas.narenas", &narenas, unsigned);
                        {
-                               bool initialized[narenas];
+                               VARIABLE_ARRAY(bool, initialized, narenas);
                                size_t isz;
                                unsigned i;
 
-                               isz = sizeof(initialized);
+                               isz = sizeof(bool) * narenas;
                                xmallctl("arenas.initialized", initialized,
                                    &isz, NULL, 0);
 
@@ -779,12 +533,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
                                                    cbopaque,
                                                    "\narenas[%u]:\n", i);
                                                stats_arena_print(write_cb,
-                                                   cbopaque, i);
+                                                   cbopaque, i, bins, large);
                                        }
                                }
                        }
                }
        }
-#endif /* #ifdef JEMALLOC_STATS */
-       write_cb(cbopaque, "--- End jemalloc statistics ---\n");
+       malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n");
 }