static void compute_bin_unused_and_bookkeeping(jemalloc_stats_t *stats, unsigned int narenas) { size_t bin_unused = 0; uint32_t nregs; // number of regions per run in the j-th bin size_t reg_size; // size of regions served by the j-th bin size_t curruns; // number of runs belonging to a bin size_t curregs; // number of allocated regions in a bin unsigned int nbins; // number of bins per arena unsigned int i, j; size_t stats_metadata; size_t stats_ametadata = 0; // total internal allocations in all arenas // narenas also counts uninitialized arenas, and initialized arenas // are not guaranteed to be adjacent VARIABLE_ARRAY(bool, initialized, narenas); size_t isz = sizeof(initialized) / sizeof(initialized[0]); je_(mallctl)("arenas.initialized", initialized, &isz, NULL, 0); CTL_GET("arenas.nbins", nbins); for (j = 0; j < nbins; j++) { CTL_I_GET("arenas.bin.0.nregs", nregs, j); CTL_I_GET("arenas.bin.0.size", reg_size, j); for (i = 0; i < narenas; i++) { if (!initialized[i]) { continue; } CTL_IJ_GET("stats.arenas.0.bins.0.curruns", curruns, i, j); CTL_IJ_GET("stats.arenas.0.bins.0.curregs", curregs, i, j); bin_unused += (nregs * curruns - curregs) * reg_size; } } CTL_GET("stats.metadata", stats_metadata); /* get the summation for all arenas, i == narenas */ CTL_I_GET("stats.arenas.0.metadata.allocated", stats_ametadata, narenas); stats->bookkeeping = stats_metadata - stats_ametadata; stats->bin_unused = bin_unused; }
static void stats_arena_hchunks_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { unsigned nbins, nlruns, nhchunks, j; bool in_gap; malloc_cprintf(write_cb, cbopaque, "huge: size ind allocated nmalloc ndalloc" " nrequests curhchunks\n"); CTL_GET("arenas.nbins", &nbins, unsigned); CTL_GET("arenas.nlruns", &nlruns, unsigned); CTL_GET("arenas.nhchunks", &nhchunks, unsigned); for (j = 0, in_gap = false; j < nhchunks; j++) { uint64_t nmalloc, ndalloc, nrequests; size_t hchunk_size, curhchunks; CTL_IJ_GET("stats.arenas.0.hchunks.0.nmalloc", &nmalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.hchunks.0.ndalloc", &ndalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.hchunks.0.nrequests", &nrequests, uint64_t); if (nrequests == 0) in_gap = true; else { CTL_J_GET("arenas.hchunk.0.size", &hchunk_size, size_t); CTL_IJ_GET("stats.arenas.0.hchunks.0.curhchunks", &curhchunks, size_t); if (in_gap) { malloc_cprintf(write_cb, cbopaque, " ---\n"); in_gap = false; } malloc_cprintf(write_cb, cbopaque, "%20zu %3u %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12zu\n", hchunk_size, nbins + nlruns + j, curhchunks * hchunk_size, nmalloc, ndalloc, nrequests, curhchunks); } } if (in_gap) { malloc_cprintf(write_cb, cbopaque, " ---\n"); } }
static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { size_t page, nlruns, j; ssize_t gap_start; CTL_GET("arenas.page", &page, size_t); malloc_cprintf(write_cb, cbopaque, "large: size pages nmalloc ndalloc nrequests" " 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, curruns; CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.lruns.0.ndalloc", &ndalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.lruns.0.nrequests", &nrequests, uint64_t); if (nrequests == 0) { if (gap_start == -1) gap_start = j; } else { CTL_J_GET("arenas.lrun.0.size", &run_size, size_t); CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns, size_t); if (gap_start != -1) { malloc_cprintf(write_cb, cbopaque, "[%zu]\n", j - gap_start); gap_start = -1; } malloc_cprintf(write_cb, cbopaque, "%13zu %5zu %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12zu\n", run_size, run_size / page, nmalloc, ndalloc, nrequests, curruns); } } if (gap_start != -1) malloc_cprintf(write_cb, cbopaque, "[%zu]\n", j - gap_start); }
static size_t compute_bin_unused(unsigned int narenas) { size_t bin_unused = 0; uint32_t nregs; // number of regions per run in the j-th bin size_t reg_size; // size of regions served by the j-th bin size_t curruns; // number of runs belonging to a bin size_t curregs; // number of allocated regions in a bin unsigned int nbins; // number of bins per arena unsigned int i, j; // narenas also counts uninitialized arenas, and initialized arenas // are not guaranteed to be adjacent VARIABLE_ARRAY(bool, initialized, narenas); size_t isz = sizeof(initialized) / sizeof(initialized[0]); je_(mallctl)("arenas.initialized", initialized, &isz, NULL, 0); CTL_GET("arenas.nbins", nbins); for (j = 0; j < nbins; j++) { CTL_I_GET("arenas.bin.0.nregs", nregs, j); CTL_I_GET("arenas.bin.0.size", reg_size, j); for (i = 0; i < narenas; i++) { if (!initialized[i]) { continue; } CTL_IJ_GET("stats.arenas.0.bins.0.curruns", curruns, i, j); CTL_IJ_GET("stats.arenas.0.bins.0.curregs", curregs, i, j); bin_unused += (nregs * curruns - curregs) * reg_size; } } return bin_unused; }
static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { size_t page; bool config_tcache; unsigned nbins, j, gap_start; 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" " ndalloc nrequests nfills nflushes" " newruns reruns curruns\n"); } else { malloc_cprintf(write_cb, cbopaque, "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++) { uint64_t nruns; CTL_IJ_GET("stats.arenas.0.bins.0.nruns", &nruns, uint64_t); if (nruns == 0) { if (gap_start == UINT_MAX) gap_start = j; } else { size_t reg_size, run_size, allocated; uint32_t nregs; uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; uint64_t reruns; size_t curruns; if (gap_start != UINT_MAX) { if (j > gap_start + 1) { /* Gap of more than one size class. */ malloc_cprintf(write_cb, cbopaque, "[%u..%u]\n", gap_start, j - 1); } else { /* Gap of one size class. */ malloc_cprintf(write_cb, cbopaque, "[%u]\n", gap_start); } gap_start = UINT_MAX; } CTL_J_GET("arenas.bin.0.size", ®_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); CTL_IJ_GET("stats.arenas.0.bins.0.allocated", &allocated, size_t); CTL_IJ_GET("stats.arenas.0.bins.0.nmalloc", &nmalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.ndalloc", &ndalloc, uint64_t); if (config_tcache) { CTL_IJ_GET("stats.arenas.0.bins.0.nrequests", &nrequests, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.nfills", &nfills, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.nflushes", &nflushes, uint64_t); } CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns, size_t); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, "%13u %5zu %4u %3zu %12zu %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12zu\n", j, reg_size, nregs, run_size / page, allocated, nmalloc, ndalloc, nrequests, nfills, nflushes, nruns, reruns, curruns); } else { malloc_cprintf(write_cb, cbopaque, "%13u %5zu %4u %3zu %12zu %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12zu\n", j, reg_size, nregs, run_size / page, allocated, nmalloc, ndalloc, nruns, reruns, curruns); } } } if (gap_start != UINT_MAX) { if (j > gap_start + 1) { /* Gap of more than one size class. */ malloc_cprintf(write_cb, cbopaque, "[%u..%u]\n", gap_start, j - 1); } else { /* Gap of one size class. */ malloc_cprintf(write_cb, cbopaque, "[%u]\n", gap_start); } } }
static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { size_t page; bool config_tcache, in_gap; unsigned nbins, j; CTL_GET("arenas.page", &page, size_t); CTL_GET("config.tcache", &config_tcache, bool); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, "bins: size ind allocated nmalloc" " ndalloc nrequests curregs curruns regs" " pgs util nfills nflushes newruns" " reruns\n"); } else { malloc_cprintf(write_cb, cbopaque, "bins: size ind allocated nmalloc" " ndalloc nrequests curregs curruns regs" " pgs util newruns reruns\n"); } CTL_GET("arenas.nbins", &nbins, unsigned); for (j = 0, in_gap = false; j < nbins; j++) { uint64_t nruns; CTL_IJ_GET("stats.arenas.0.bins.0.nruns", &nruns, uint64_t); if (nruns == 0) in_gap = true; else { size_t reg_size, run_size, curregs, availregs, milli; size_t curruns; uint32_t nregs; uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; uint64_t reruns; char util[6]; /* "x.yyy". */ if (in_gap) { malloc_cprintf(write_cb, cbopaque, " ---\n"); in_gap = false; } CTL_J_GET("arenas.bin.0.size", ®_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); CTL_IJ_GET("stats.arenas.0.bins.0.nmalloc", &nmalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.ndalloc", &ndalloc, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.curregs", &curregs, size_t); CTL_IJ_GET("stats.arenas.0.bins.0.nrequests", &nrequests, uint64_t); if (config_tcache) { CTL_IJ_GET("stats.arenas.0.bins.0.nfills", &nfills, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.nflushes", &nflushes, uint64_t); } CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns, uint64_t); CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns, size_t); availregs = nregs * curruns; milli = (availregs != 0) ? (1000 * curregs) / availregs : 1000; assert(milli <= 1000); if (milli < 10) { malloc_snprintf(util, sizeof(util), "0.00%zu", milli); } else if (milli < 100) { malloc_snprintf(util, sizeof(util), "0.0%zu", milli); } else if (milli < 1000) { malloc_snprintf(util, sizeof(util), "0.%zu", milli); } else malloc_snprintf(util, sizeof(util), "1"); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, "%20zu %3u %12zu %12"PRIu64" %12"PRIu64 " %12"PRIu64" %12zu %12zu %4u %3zu %-5s" " %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12"PRIu64"\n", reg_size, j, curregs * reg_size, nmalloc, ndalloc, nrequests, curregs, curruns, nregs, run_size / page, util, nfills, nflushes, nruns, reruns); } else { malloc_cprintf(write_cb, cbopaque, "%20zu %3u %12zu %12"PRIu64" %12"PRIu64 " %12"PRIu64" %12zu %12zu %4u %3zu %-5s" " %12"PRIu64" %12"PRIu64"\n", reg_size, j, curregs * reg_size, nmalloc, ndalloc, nrequests, curregs, curruns, nregs, run_size / page, util, nruns, reruns); } } } if (in_gap) { malloc_cprintf(write_cb, cbopaque, " ---\n"); } }