1234370Sjasone#define JEMALLOC_STATS_C_ 2234370Sjasone#include "jemalloc/internal/jemalloc_internal.h" 3234370Sjasone 4234370Sjasone#define CTL_GET(n, v, t) do { \ 5234370Sjasone size_t sz = sizeof(t); \ 6234370Sjasone xmallctl(n, v, &sz, NULL, 0); \ 7234370Sjasone} while (0) 8234370Sjasone 9286866Sjasone#define CTL_M2_GET(n, i, v, t) do { \ 10234370Sjasone size_t mib[6]; \ 11234370Sjasone size_t miblen = sizeof(mib) / sizeof(size_t); \ 12234370Sjasone size_t sz = sizeof(t); \ 13234370Sjasone xmallctlnametomib(n, mib, &miblen); \ 14286866Sjasone mib[2] = (i); \ 15234370Sjasone xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ 16234370Sjasone} while (0) 17234370Sjasone 18286866Sjasone#define CTL_M2_M4_GET(n, i, j, v, t) do { \ 19234370Sjasone size_t mib[6]; \ 20234370Sjasone size_t miblen = sizeof(mib) / sizeof(size_t); \ 21234370Sjasone size_t sz = sizeof(t); \ 22234370Sjasone xmallctlnametomib(n, mib, &miblen); \ 23286866Sjasone mib[2] = (i); \ 24286866Sjasone mib[4] = (j); \ 25234370Sjasone xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ 26234370Sjasone} while (0) 27234370Sjasone 28234370Sjasone/******************************************************************************/ 29234370Sjasone/* Data. */ 30234370Sjasone 31234370Sjasonebool opt_stats_print = false; 32234370Sjasone 33234370Sjasonesize_t stats_cactive = 0; 34234370Sjasone 35234370Sjasone/******************************************************************************/ 36234370Sjasone/* Function prototypes for non-inline static functions. */ 37234370Sjasone 38234370Sjasonestatic void stats_arena_bins_print(void (*write_cb)(void *, const char *), 39234370Sjasone void *cbopaque, unsigned i); 40234370Sjasonestatic void stats_arena_lruns_print(void (*write_cb)(void *, const char *), 41234370Sjasone void *cbopaque, unsigned i); 42286866Sjasonestatic void stats_arena_hchunks_print( 43286866Sjasone void (*write_cb)(void *, const char *), void *cbopaque, unsigned i); 44234370Sjasonestatic void stats_arena_print(void (*write_cb)(void *, const char *), 45286866Sjasone void *cbopaque, unsigned i, bool bins, bool large, bool huge); 46234370Sjasone 47234370Sjasone/******************************************************************************/ 48234370Sjasone 49234370Sjasonestatic void 50234370Sjasonestats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, 51234370Sjasone unsigned i) 52234370Sjasone{ 53234370Sjasone size_t page; 54286866Sjasone bool config_tcache, in_gap; 55286866Sjasone unsigned nbins, j; 56234370Sjasone 57234370Sjasone CTL_GET("arenas.page", &page, size_t); 58234370Sjasone 59234370Sjasone CTL_GET("config.tcache", &config_tcache, bool); 60234370Sjasone if (config_tcache) { 61234370Sjasone malloc_cprintf(write_cb, cbopaque, 62286866Sjasone "bins: size ind allocated nmalloc" 63286866Sjasone " ndalloc nrequests curregs curruns regs" 64286866Sjasone " pgs util nfills nflushes newruns" 65286866Sjasone " reruns\n"); 66234370Sjasone } else { 67234370Sjasone malloc_cprintf(write_cb, cbopaque, 68286866Sjasone "bins: size ind allocated nmalloc" 69286866Sjasone " ndalloc nrequests curregs curruns regs" 70286866Sjasone " pgs util newruns reruns\n"); 71234370Sjasone } 72234370Sjasone CTL_GET("arenas.nbins", &nbins, unsigned); 73286866Sjasone for (j = 0, in_gap = false; j < nbins; j++) { 74234370Sjasone uint64_t nruns; 75234370Sjasone 76286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nruns", i, j, &nruns, 77286866Sjasone uint64_t); 78286866Sjasone if (nruns == 0) 79286866Sjasone in_gap = true; 80286866Sjasone else { 81286866Sjasone size_t reg_size, run_size, curregs, availregs, milli; 82286866Sjasone size_t curruns; 83234370Sjasone uint32_t nregs; 84234370Sjasone uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; 85234370Sjasone uint64_t reruns; 86286866Sjasone char util[6]; /* "x.yyy". */ 87234370Sjasone 88286866Sjasone if (in_gap) { 89286866Sjasone malloc_cprintf(write_cb, cbopaque, 90286866Sjasone " ---\n"); 91286866Sjasone in_gap = false; 92234370Sjasone } 93286866Sjasone CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t); 94286866Sjasone CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t); 95286866Sjasone CTL_M2_GET("arenas.bin.0.run_size", j, &run_size, 96286866Sjasone size_t); 97286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j, 98234370Sjasone &nmalloc, uint64_t); 99286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j, 100234370Sjasone &ndalloc, uint64_t); 101286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j, 102286866Sjasone &curregs, size_t); 103286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j, 104286866Sjasone &nrequests, uint64_t); 105234370Sjasone if (config_tcache) { 106286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i, 107286866Sjasone j, &nfills, uint64_t); 108286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes", 109286866Sjasone i, j, &nflushes, uint64_t); 110234370Sjasone } 111286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.nreruns", i, j, 112286866Sjasone &reruns, uint64_t); 113286866Sjasone CTL_M2_M4_GET("stats.arenas.0.bins.0.curruns", i, j, 114286866Sjasone &curruns, size_t); 115286866Sjasone 116286866Sjasone availregs = nregs * curruns; 117286866Sjasone milli = (availregs != 0) ? (1000 * curregs) / availregs 118286866Sjasone : 1000; 119286866Sjasone assert(milli <= 1000); 120286866Sjasone if (milli < 10) { 121286866Sjasone malloc_snprintf(util, sizeof(util), 122286866Sjasone "0.00%zu", milli); 123286866Sjasone } else if (milli < 100) { 124286866Sjasone malloc_snprintf(util, sizeof(util), "0.0%zu", 125286866Sjasone milli); 126286866Sjasone } else if (milli < 1000) { 127286866Sjasone malloc_snprintf(util, sizeof(util), "0.%zu", 128286866Sjasone milli); 129286866Sjasone } else 130286866Sjasone malloc_snprintf(util, sizeof(util), "1"); 131286866Sjasone 132234370Sjasone if (config_tcache) { 133234370Sjasone malloc_cprintf(write_cb, cbopaque, 134286866Sjasone "%20zu %3u %12zu %12"FMTu64 135286866Sjasone " %12"FMTu64" %12"FMTu64" %12zu" 136286866Sjasone " %12zu %4u %3zu %-5s %12"FMTu64 137286866Sjasone " %12"FMTu64" %12"FMTu64" %12"FMTu64"\n", 138286866Sjasone reg_size, j, curregs * reg_size, nmalloc, 139286866Sjasone ndalloc, nrequests, curregs, curruns, nregs, 140286866Sjasone run_size / page, util, nfills, nflushes, 141286866Sjasone nruns, reruns); 142234370Sjasone } else { 143234370Sjasone malloc_cprintf(write_cb, cbopaque, 144286866Sjasone "%20zu %3u %12zu %12"FMTu64 145286866Sjasone " %12"FMTu64" %12"FMTu64" %12zu" 146286866Sjasone " %12zu %4u %3zu %-5s %12"FMTu64 147286866Sjasone " %12"FMTu64"\n", 148286866Sjasone reg_size, j, curregs * reg_size, nmalloc, 149286866Sjasone ndalloc, nrequests, curregs, curruns, nregs, 150286866Sjasone run_size / page, util, nruns, reruns); 151234370Sjasone } 152234370Sjasone } 153234370Sjasone } 154286866Sjasone if (in_gap) { 155286866Sjasone malloc_cprintf(write_cb, cbopaque, 156286866Sjasone " ---\n"); 157234370Sjasone } 158234370Sjasone} 159234370Sjasone 160234370Sjasonestatic void 161234370Sjasonestats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, 162234370Sjasone unsigned i) 163234370Sjasone{ 164286866Sjasone unsigned nbins, nlruns, j; 165286866Sjasone bool in_gap; 166234370Sjasone 167234370Sjasone malloc_cprintf(write_cb, cbopaque, 168286866Sjasone "large: size ind allocated nmalloc ndalloc" 169286866Sjasone " nrequests curruns\n"); 170286866Sjasone CTL_GET("arenas.nbins", &nbins, unsigned); 171286866Sjasone CTL_GET("arenas.nlruns", &nlruns, unsigned); 172286866Sjasone for (j = 0, in_gap = false; j < nlruns; j++) { 173234370Sjasone uint64_t nmalloc, ndalloc, nrequests; 174234370Sjasone size_t run_size, curruns; 175234370Sjasone 176286866Sjasone CTL_M2_M4_GET("stats.arenas.0.lruns.0.nmalloc", i, j, &nmalloc, 177234370Sjasone uint64_t); 178286866Sjasone CTL_M2_M4_GET("stats.arenas.0.lruns.0.ndalloc", i, j, &ndalloc, 179234370Sjasone uint64_t); 180286866Sjasone CTL_M2_M4_GET("stats.arenas.0.lruns.0.nrequests", i, j, 181286866Sjasone &nrequests, uint64_t); 182286866Sjasone if (nrequests == 0) 183286866Sjasone in_gap = true; 184286866Sjasone else { 185286866Sjasone CTL_M2_GET("arenas.lrun.0.size", j, &run_size, size_t); 186286866Sjasone CTL_M2_M4_GET("stats.arenas.0.lruns.0.curruns", i, j, 187286866Sjasone &curruns, size_t); 188286866Sjasone if (in_gap) { 189286866Sjasone malloc_cprintf(write_cb, cbopaque, 190286866Sjasone " ---\n"); 191286866Sjasone in_gap = false; 192286866Sjasone } 193286866Sjasone malloc_cprintf(write_cb, cbopaque, 194286866Sjasone "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 195286866Sjasone " %12"FMTu64" %12zu\n", 196286866Sjasone run_size, nbins + j, curruns * run_size, nmalloc, 197286866Sjasone ndalloc, nrequests, curruns); 198286866Sjasone } 199286866Sjasone } 200286866Sjasone if (in_gap) { 201286866Sjasone malloc_cprintf(write_cb, cbopaque, 202286866Sjasone " ---\n"); 203286866Sjasone } 204286866Sjasone} 205286866Sjasone 206286866Sjasonestatic void 207286866Sjasonestats_arena_hchunks_print(void (*write_cb)(void *, const char *), 208286866Sjasone void *cbopaque, unsigned i) 209286866Sjasone{ 210286866Sjasone unsigned nbins, nlruns, nhchunks, j; 211286866Sjasone bool in_gap; 212286866Sjasone 213286866Sjasone malloc_cprintf(write_cb, cbopaque, 214286866Sjasone "huge: size ind allocated nmalloc ndalloc" 215286866Sjasone " nrequests curhchunks\n"); 216286866Sjasone CTL_GET("arenas.nbins", &nbins, unsigned); 217286866Sjasone CTL_GET("arenas.nlruns", &nlruns, unsigned); 218286866Sjasone CTL_GET("arenas.nhchunks", &nhchunks, unsigned); 219286866Sjasone for (j = 0, in_gap = false; j < nhchunks; j++) { 220286866Sjasone uint64_t nmalloc, ndalloc, nrequests; 221286866Sjasone size_t hchunk_size, curhchunks; 222286866Sjasone 223286866Sjasone CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nmalloc", i, j, 224286866Sjasone &nmalloc, uint64_t); 225286866Sjasone CTL_M2_M4_GET("stats.arenas.0.hchunks.0.ndalloc", i, j, 226286866Sjasone &ndalloc, uint64_t); 227286866Sjasone CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nrequests", i, j, 228286866Sjasone &nrequests, uint64_t); 229286866Sjasone if (nrequests == 0) 230286866Sjasone in_gap = true; 231286866Sjasone else { 232286866Sjasone CTL_M2_GET("arenas.hchunk.0.size", j, &hchunk_size, 233234370Sjasone size_t); 234286866Sjasone CTL_M2_M4_GET("stats.arenas.0.hchunks.0.curhchunks", i, 235286866Sjasone j, &curhchunks, size_t); 236286866Sjasone if (in_gap) { 237286866Sjasone malloc_cprintf(write_cb, cbopaque, 238286866Sjasone " ---\n"); 239286866Sjasone in_gap = false; 240234370Sjasone } 241234370Sjasone malloc_cprintf(write_cb, cbopaque, 242286866Sjasone "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 243286866Sjasone " %12"FMTu64" %12zu\n", 244286866Sjasone hchunk_size, nbins + nlruns + j, 245286866Sjasone curhchunks * hchunk_size, nmalloc, ndalloc, 246286866Sjasone nrequests, curhchunks); 247234370Sjasone } 248234370Sjasone } 249286866Sjasone if (in_gap) { 250286866Sjasone malloc_cprintf(write_cb, cbopaque, 251286866Sjasone " ---\n"); 252286866Sjasone } 253234370Sjasone} 254234370Sjasone 255234370Sjasonestatic void 256234370Sjasonestats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, 257286866Sjasone unsigned i, bool bins, bool large, bool huge) 258234370Sjasone{ 259234370Sjasone unsigned nthreads; 260242844Sjasone const char *dss; 261296221Sjasone ssize_t lg_dirty_mult, decay_time; 262299587Sjasone size_t page, pactive, pdirty, mapped, retained; 263286866Sjasone size_t metadata_mapped, metadata_allocated; 264234370Sjasone uint64_t npurge, nmadvise, purged; 265234370Sjasone size_t small_allocated; 266234370Sjasone uint64_t small_nmalloc, small_ndalloc, small_nrequests; 267234370Sjasone size_t large_allocated; 268234370Sjasone uint64_t large_nmalloc, large_ndalloc, large_nrequests; 269286866Sjasone size_t huge_allocated; 270286866Sjasone uint64_t huge_nmalloc, huge_ndalloc, huge_nrequests; 271234370Sjasone 272234370Sjasone CTL_GET("arenas.page", &page, size_t); 273234370Sjasone 274286866Sjasone CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned); 275234370Sjasone malloc_cprintf(write_cb, cbopaque, 276234370Sjasone "assigned threads: %u\n", nthreads); 277286866Sjasone CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *); 278242844Sjasone malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n", 279242844Sjasone dss); 280286866Sjasone CTL_M2_GET("stats.arenas.0.lg_dirty_mult", i, &lg_dirty_mult, ssize_t); 281296221Sjasone if (opt_purge == purge_mode_ratio) { 282296221Sjasone if (lg_dirty_mult >= 0) { 283296221Sjasone malloc_cprintf(write_cb, cbopaque, 284296221Sjasone "min active:dirty page ratio: %u:1\n", 285296221Sjasone (1U << lg_dirty_mult)); 286296221Sjasone } else { 287296221Sjasone malloc_cprintf(write_cb, cbopaque, 288296221Sjasone "min active:dirty page ratio: N/A\n"); 289296221Sjasone } 290286866Sjasone } 291296221Sjasone CTL_M2_GET("stats.arenas.0.decay_time", i, &decay_time, ssize_t); 292296221Sjasone if (opt_purge == purge_mode_decay) { 293296221Sjasone if (decay_time >= 0) { 294296221Sjasone malloc_cprintf(write_cb, cbopaque, "decay time: %zd\n", 295296221Sjasone decay_time); 296296221Sjasone } else 297296221Sjasone malloc_cprintf(write_cb, cbopaque, "decay time: N/A\n"); 298296221Sjasone } 299286866Sjasone CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t); 300286866Sjasone CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t); 301286866Sjasone CTL_M2_GET("stats.arenas.0.npurge", i, &npurge, uint64_t); 302286866Sjasone CTL_M2_GET("stats.arenas.0.nmadvise", i, &nmadvise, uint64_t); 303286866Sjasone CTL_M2_GET("stats.arenas.0.purged", i, &purged, uint64_t); 304234370Sjasone malloc_cprintf(write_cb, cbopaque, 305296221Sjasone "purging: dirty: %zu, sweeps: %"FMTu64", madvises: %"FMTu64", " 306296221Sjasone "purged: %"FMTu64"\n", pdirty, npurge, nmadvise, purged); 307234370Sjasone 308234370Sjasone malloc_cprintf(write_cb, cbopaque, 309286866Sjasone " allocated nmalloc ndalloc" 310286866Sjasone " nrequests\n"); 311286866Sjasone CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated, 312286866Sjasone size_t); 313286866Sjasone CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t); 314286866Sjasone CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t); 315286866Sjasone CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests, 316286866Sjasone uint64_t); 317234370Sjasone malloc_cprintf(write_cb, cbopaque, 318286866Sjasone "small: %12zu %12"FMTu64" %12"FMTu64 319286866Sjasone " %12"FMTu64"\n", 320234370Sjasone small_allocated, small_nmalloc, small_ndalloc, small_nrequests); 321286866Sjasone CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated, 322286866Sjasone size_t); 323286866Sjasone CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t); 324286866Sjasone CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t); 325286866Sjasone CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests, 326286866Sjasone uint64_t); 327234370Sjasone malloc_cprintf(write_cb, cbopaque, 328286866Sjasone "large: %12zu %12"FMTu64" %12"FMTu64 329286866Sjasone " %12"FMTu64"\n", 330234370Sjasone large_allocated, large_nmalloc, large_ndalloc, large_nrequests); 331286866Sjasone CTL_M2_GET("stats.arenas.0.huge.allocated", i, &huge_allocated, size_t); 332286866Sjasone CTL_M2_GET("stats.arenas.0.huge.nmalloc", i, &huge_nmalloc, uint64_t); 333286866Sjasone CTL_M2_GET("stats.arenas.0.huge.ndalloc", i, &huge_ndalloc, uint64_t); 334286866Sjasone CTL_M2_GET("stats.arenas.0.huge.nrequests", i, &huge_nrequests, 335286866Sjasone uint64_t); 336234370Sjasone malloc_cprintf(write_cb, cbopaque, 337286866Sjasone "huge: %12zu %12"FMTu64" %12"FMTu64 338286866Sjasone " %12"FMTu64"\n", 339286866Sjasone huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests); 340286866Sjasone malloc_cprintf(write_cb, cbopaque, 341286866Sjasone "total: %12zu %12"FMTu64" %12"FMTu64 342286866Sjasone " %12"FMTu64"\n", 343286866Sjasone small_allocated + large_allocated + huge_allocated, 344286866Sjasone small_nmalloc + large_nmalloc + huge_nmalloc, 345286866Sjasone small_ndalloc + large_ndalloc + huge_ndalloc, 346286866Sjasone small_nrequests + large_nrequests + huge_nrequests); 347286866Sjasone malloc_cprintf(write_cb, cbopaque, 348286866Sjasone "active: %12zu\n", pactive * page); 349286866Sjasone CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t); 350286866Sjasone malloc_cprintf(write_cb, cbopaque, 351286866Sjasone "mapped: %12zu\n", mapped); 352299587Sjasone CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t); 353299587Sjasone malloc_cprintf(write_cb, cbopaque, 354299587Sjasone "retained: %12zu\n", retained); 355286866Sjasone CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped, 356286866Sjasone size_t); 357286866Sjasone CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated, 358286866Sjasone size_t); 359286866Sjasone malloc_cprintf(write_cb, cbopaque, 360286866Sjasone "metadata: mapped: %zu, allocated: %zu\n", 361286866Sjasone metadata_mapped, metadata_allocated); 362234370Sjasone 363234370Sjasone if (bins) 364234370Sjasone stats_arena_bins_print(write_cb, cbopaque, i); 365234370Sjasone if (large) 366234370Sjasone stats_arena_lruns_print(write_cb, cbopaque, i); 367286866Sjasone if (huge) 368286866Sjasone stats_arena_hchunks_print(write_cb, cbopaque, i); 369234370Sjasone} 370234370Sjasone 371234370Sjasonevoid 372234370Sjasonestats_print(void (*write_cb)(void *, const char *), void *cbopaque, 373234370Sjasone const char *opts) 374234370Sjasone{ 375234370Sjasone int err; 376234370Sjasone uint64_t epoch; 377234370Sjasone size_t u64sz; 378234370Sjasone bool general = true; 379234370Sjasone bool merged = true; 380234370Sjasone bool unmerged = true; 381234370Sjasone bool bins = true; 382234370Sjasone bool large = true; 383286866Sjasone bool huge = true; 384234370Sjasone 385234370Sjasone /* 386234370Sjasone * Refresh stats, in case mallctl() was called by the application. 387234370Sjasone * 388234370Sjasone * Check for OOM here, since refreshing the ctl cache can trigger 389234370Sjasone * allocation. In practice, none of the subsequent mallctl()-related 390234370Sjasone * calls in this function will cause OOM if this one succeeds. 391234370Sjasone * */ 392234370Sjasone epoch = 1; 393234370Sjasone u64sz = sizeof(uint64_t); 394234370Sjasone err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t)); 395234370Sjasone if (err != 0) { 396234370Sjasone if (err == EAGAIN) { 397234370Sjasone malloc_write("<jemalloc>: Memory allocation failure in " 398234370Sjasone "mallctl(\"epoch\", ...)\n"); 399234370Sjasone return; 400234370Sjasone } 401234370Sjasone malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", " 402234370Sjasone "...)\n"); 403234370Sjasone abort(); 404234370Sjasone } 405234370Sjasone 406234370Sjasone if (opts != NULL) { 407234370Sjasone unsigned i; 408234370Sjasone 409234370Sjasone for (i = 0; opts[i] != '\0'; i++) { 410234370Sjasone switch (opts[i]) { 411234370Sjasone case 'g': 412234370Sjasone general = false; 413234370Sjasone break; 414234370Sjasone case 'm': 415234370Sjasone merged = false; 416234370Sjasone break; 417234370Sjasone case 'a': 418234370Sjasone unmerged = false; 419234370Sjasone break; 420234370Sjasone case 'b': 421234370Sjasone bins = false; 422234370Sjasone break; 423234370Sjasone case 'l': 424234370Sjasone large = false; 425234370Sjasone break; 426286866Sjasone case 'h': 427286866Sjasone huge = false; 428286866Sjasone break; 429234370Sjasone default:; 430234370Sjasone } 431234370Sjasone } 432234370Sjasone } 433234370Sjasone 434235238Sjasone malloc_cprintf(write_cb, cbopaque, 435235238Sjasone "___ Begin jemalloc statistics ___\n"); 436234370Sjasone if (general) { 437234370Sjasone const char *cpv; 438234370Sjasone bool bv; 439234370Sjasone unsigned uv; 440234370Sjasone ssize_t ssv; 441296221Sjasone size_t sv, bsz, usz, ssz, sssz, cpsz; 442234370Sjasone 443234370Sjasone bsz = sizeof(bool); 444296221Sjasone usz = sizeof(unsigned); 445234370Sjasone ssz = sizeof(size_t); 446234370Sjasone sssz = sizeof(ssize_t); 447234370Sjasone cpsz = sizeof(const char *); 448234370Sjasone 449234370Sjasone CTL_GET("version", &cpv, const char *); 450234370Sjasone malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv); 451234370Sjasone CTL_GET("config.debug", &bv, bool); 452234370Sjasone malloc_cprintf(write_cb, cbopaque, "Assertions %s\n", 453234370Sjasone bv ? "enabled" : "disabled"); 454296221Sjasone malloc_cprintf(write_cb, cbopaque, 455296221Sjasone "config.malloc_conf: \"%s\"\n", config_malloc_conf); 456234370Sjasone 457261071Sjasone#define OPT_WRITE_BOOL(n) \ 458286866Sjasone if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0) { \ 459234370Sjasone malloc_cprintf(write_cb, cbopaque, \ 460234370Sjasone " opt."#n": %s\n", bv ? "true" : "false"); \ 461234370Sjasone } 462286866Sjasone#define OPT_WRITE_BOOL_MUTABLE(n, m) { \ 463286866Sjasone bool bv2; \ 464286866Sjasone if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0 && \ 465286866Sjasone je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) { \ 466286866Sjasone malloc_cprintf(write_cb, cbopaque, \ 467286866Sjasone " opt."#n": %s ("#m": %s)\n", bv ? "true" \ 468286866Sjasone : "false", bv2 ? "true" : "false"); \ 469286866Sjasone } \ 470286866Sjasone} 471296221Sjasone#define OPT_WRITE_UNSIGNED(n) \ 472296221Sjasone if (je_mallctl("opt."#n, &uv, &usz, NULL, 0) == 0) { \ 473296221Sjasone malloc_cprintf(write_cb, cbopaque, \ 474299587Sjasone " opt."#n": %u\n", uv); \ 475296221Sjasone } 476261071Sjasone#define OPT_WRITE_SIZE_T(n) \ 477286866Sjasone if (je_mallctl("opt."#n, &sv, &ssz, NULL, 0) == 0) { \ 478234370Sjasone malloc_cprintf(write_cb, cbopaque, \ 479234370Sjasone " opt."#n": %zu\n", sv); \ 480234370Sjasone } 481261071Sjasone#define OPT_WRITE_SSIZE_T(n) \ 482286866Sjasone if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0) { \ 483234370Sjasone malloc_cprintf(write_cb, cbopaque, \ 484234370Sjasone " opt."#n": %zd\n", ssv); \ 485234370Sjasone } 486286866Sjasone#define OPT_WRITE_SSIZE_T_MUTABLE(n, m) { \ 487286866Sjasone ssize_t ssv2; \ 488286866Sjasone if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0 && \ 489286866Sjasone je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) { \ 490286866Sjasone malloc_cprintf(write_cb, cbopaque, \ 491286866Sjasone " opt."#n": %zd ("#m": %zd)\n", \ 492286866Sjasone ssv, ssv2); \ 493286866Sjasone } \ 494286866Sjasone} 495261071Sjasone#define OPT_WRITE_CHAR_P(n) \ 496286866Sjasone if (je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0) == 0) { \ 497234370Sjasone malloc_cprintf(write_cb, cbopaque, \ 498234370Sjasone " opt."#n": \"%s\"\n", cpv); \ 499234370Sjasone } 500234370Sjasone 501235238Sjasone malloc_cprintf(write_cb, cbopaque, 502235238Sjasone "Run-time option settings:\n"); 503234370Sjasone OPT_WRITE_BOOL(abort) 504234370Sjasone OPT_WRITE_SIZE_T(lg_chunk) 505242844Sjasone OPT_WRITE_CHAR_P(dss) 506296221Sjasone OPT_WRITE_UNSIGNED(narenas) 507296221Sjasone OPT_WRITE_CHAR_P(purge) 508296221Sjasone if (opt_purge == purge_mode_ratio) { 509296221Sjasone OPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult, 510296221Sjasone arenas.lg_dirty_mult) 511296221Sjasone } 512296221Sjasone if (opt_purge == purge_mode_decay) 513296221Sjasone OPT_WRITE_SSIZE_T_MUTABLE(decay_time, arenas.decay_time) 514234370Sjasone OPT_WRITE_BOOL(stats_print) 515286866Sjasone OPT_WRITE_CHAR_P(junk) 516234370Sjasone OPT_WRITE_SIZE_T(quarantine) 517234370Sjasone OPT_WRITE_BOOL(redzone) 518234370Sjasone OPT_WRITE_BOOL(zero) 519234370Sjasone OPT_WRITE_BOOL(utrace) 520234370Sjasone OPT_WRITE_BOOL(valgrind) 521234370Sjasone OPT_WRITE_BOOL(xmalloc) 522234370Sjasone OPT_WRITE_BOOL(tcache) 523234370Sjasone OPT_WRITE_SSIZE_T(lg_tcache_max) 524234370Sjasone OPT_WRITE_BOOL(prof) 525234370Sjasone OPT_WRITE_CHAR_P(prof_prefix) 526286866Sjasone OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active) 527286866Sjasone OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, 528286866Sjasone prof.thread_active_init) 529234370Sjasone OPT_WRITE_SSIZE_T(lg_prof_sample) 530234370Sjasone OPT_WRITE_BOOL(prof_accum) 531234370Sjasone OPT_WRITE_SSIZE_T(lg_prof_interval) 532234370Sjasone OPT_WRITE_BOOL(prof_gdump) 533234543Sjasone OPT_WRITE_BOOL(prof_final) 534234370Sjasone OPT_WRITE_BOOL(prof_leak) 535234370Sjasone 536234370Sjasone#undef OPT_WRITE_BOOL 537286866Sjasone#undef OPT_WRITE_BOOL_MUTABLE 538234370Sjasone#undef OPT_WRITE_SIZE_T 539234370Sjasone#undef OPT_WRITE_SSIZE_T 540234370Sjasone#undef OPT_WRITE_CHAR_P 541234370Sjasone 542234370Sjasone malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus); 543234370Sjasone 544234370Sjasone CTL_GET("arenas.narenas", &uv, unsigned); 545242844Sjasone malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); 546234370Sjasone 547234370Sjasone malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n", 548234370Sjasone sizeof(void *)); 549234370Sjasone 550234370Sjasone CTL_GET("arenas.quantum", &sv, size_t); 551286866Sjasone malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", 552286866Sjasone sv); 553234370Sjasone 554234370Sjasone CTL_GET("arenas.page", &sv, size_t); 555234370Sjasone malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); 556234370Sjasone 557286866Sjasone CTL_GET("arenas.lg_dirty_mult", &ssv, ssize_t); 558296221Sjasone if (opt_purge == purge_mode_ratio) { 559296221Sjasone if (ssv >= 0) { 560296221Sjasone malloc_cprintf(write_cb, cbopaque, 561296221Sjasone "Min active:dirty page ratio per arena: " 562296221Sjasone "%u:1\n", (1U << ssv)); 563296221Sjasone } else { 564296221Sjasone malloc_cprintf(write_cb, cbopaque, 565296221Sjasone "Min active:dirty page ratio per arena: " 566296221Sjasone "N/A\n"); 567296221Sjasone } 568296221Sjasone } 569296221Sjasone CTL_GET("arenas.decay_time", &ssv, ssize_t); 570296221Sjasone if (opt_purge == purge_mode_decay) { 571234370Sjasone malloc_cprintf(write_cb, cbopaque, 572296221Sjasone "Unused dirty page decay time: %zd%s\n", 573296221Sjasone ssv, (ssv < 0) ? " (no decay)" : ""); 574234370Sjasone } 575286866Sjasone if (je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0) == 0) { 576234370Sjasone malloc_cprintf(write_cb, cbopaque, 577234370Sjasone "Maximum thread-cached size class: %zu\n", sv); 578234370Sjasone } 579286866Sjasone if (je_mallctl("opt.prof", &bv, &bsz, NULL, 0) == 0 && bv) { 580286866Sjasone CTL_GET("prof.lg_sample", &sv, size_t); 581234370Sjasone malloc_cprintf(write_cb, cbopaque, 582286866Sjasone "Average profile sample interval: %"FMTu64 583234370Sjasone " (2^%zu)\n", (((uint64_t)1U) << sv), sv); 584234370Sjasone 585234370Sjasone CTL_GET("opt.lg_prof_interval", &ssv, ssize_t); 586234370Sjasone if (ssv >= 0) { 587234370Sjasone malloc_cprintf(write_cb, cbopaque, 588286866Sjasone "Average profile dump interval: %"FMTu64 589234370Sjasone " (2^%zd)\n", 590234370Sjasone (((uint64_t)1U) << ssv), ssv); 591234370Sjasone } else { 592235238Sjasone malloc_cprintf(write_cb, cbopaque, 593234370Sjasone "Average profile dump interval: N/A\n"); 594234370Sjasone } 595234370Sjasone } 596234370Sjasone CTL_GET("opt.lg_chunk", &sv, size_t); 597286866Sjasone malloc_cprintf(write_cb, cbopaque, 598286866Sjasone "Chunk size: %zu (2^%zu)\n", (ZU(1) << sv), sv); 599234370Sjasone } 600234370Sjasone 601234370Sjasone if (config_stats) { 602234370Sjasone size_t *cactive; 603299587Sjasone size_t allocated, active, metadata, resident, mapped, retained; 604234370Sjasone 605234370Sjasone CTL_GET("stats.cactive", &cactive, size_t *); 606234370Sjasone CTL_GET("stats.allocated", &allocated, size_t); 607234370Sjasone CTL_GET("stats.active", &active, size_t); 608286866Sjasone CTL_GET("stats.metadata", &metadata, size_t); 609286866Sjasone CTL_GET("stats.resident", &resident, size_t); 610234370Sjasone CTL_GET("stats.mapped", &mapped, size_t); 611299587Sjasone CTL_GET("stats.retained", &retained, size_t); 612234370Sjasone malloc_cprintf(write_cb, cbopaque, 613286866Sjasone "Allocated: %zu, active: %zu, metadata: %zu," 614299587Sjasone " resident: %zu, mapped: %zu, retained: %zu\n", 615299587Sjasone allocated, active, metadata, resident, mapped, retained); 616234370Sjasone malloc_cprintf(write_cb, cbopaque, 617286866Sjasone "Current active ceiling: %zu\n", 618286866Sjasone atomic_read_z(cactive)); 619234370Sjasone 620234370Sjasone if (merged) { 621234370Sjasone unsigned narenas; 622234370Sjasone 623234370Sjasone CTL_GET("arenas.narenas", &narenas, unsigned); 624234370Sjasone { 625235238Sjasone VARIABLE_ARRAY(bool, initialized, narenas); 626234370Sjasone size_t isz; 627234370Sjasone unsigned i, ninitialized; 628234370Sjasone 629235238Sjasone isz = sizeof(bool) * narenas; 630234370Sjasone xmallctl("arenas.initialized", initialized, 631234370Sjasone &isz, NULL, 0); 632234370Sjasone for (i = ninitialized = 0; i < narenas; i++) { 633234370Sjasone if (initialized[i]) 634234370Sjasone ninitialized++; 635234370Sjasone } 636234370Sjasone 637286866Sjasone if (ninitialized > 1 || !unmerged) { 638234370Sjasone /* Print merged arena stats. */ 639234370Sjasone malloc_cprintf(write_cb, cbopaque, 640234370Sjasone "\nMerged arenas stats:\n"); 641234370Sjasone stats_arena_print(write_cb, cbopaque, 642286866Sjasone narenas, bins, large, huge); 643234370Sjasone } 644234370Sjasone } 645234370Sjasone } 646234370Sjasone 647234370Sjasone if (unmerged) { 648234370Sjasone unsigned narenas; 649234370Sjasone 650234370Sjasone /* Print stats for each arena. */ 651234370Sjasone 652234370Sjasone CTL_GET("arenas.narenas", &narenas, unsigned); 653234370Sjasone { 654235238Sjasone VARIABLE_ARRAY(bool, initialized, narenas); 655234370Sjasone size_t isz; 656234370Sjasone unsigned i; 657234370Sjasone 658235238Sjasone isz = sizeof(bool) * narenas; 659234370Sjasone xmallctl("arenas.initialized", initialized, 660234370Sjasone &isz, NULL, 0); 661234370Sjasone 662234370Sjasone for (i = 0; i < narenas; i++) { 663234370Sjasone if (initialized[i]) { 664234370Sjasone malloc_cprintf(write_cb, 665234370Sjasone cbopaque, 666234370Sjasone "\narenas[%u]:\n", i); 667234370Sjasone stats_arena_print(write_cb, 668286866Sjasone cbopaque, i, bins, large, 669286866Sjasone huge); 670234370Sjasone } 671234370Sjasone } 672234370Sjasone } 673234370Sjasone } 674234370Sjasone } 675235238Sjasone malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n"); 676234370Sjasone} 677