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; }
MOZ_JEMALLOC_API void jemalloc_stats_impl(jemalloc_stats_t *stats) { unsigned narenas; size_t active, allocated, mapped, page, pdirty; size_t lg_chunk; // Refresh jemalloc's stats by updating its epoch, see ctl_refresh in // src/ctl.c uint64_t epoch = 0; size_t esz = sizeof(epoch); int ret = je_(mallctl)("epoch", &epoch, &esz, &epoch, esz); CTL_GET("arenas.narenas", narenas); CTL_GET("arenas.page", page); CTL_GET("stats.active", active); CTL_GET("stats.allocated", allocated); CTL_GET("stats.mapped", mapped); CTL_GET("opt.lg_chunk", lg_chunk); CTL_GET("stats.bookkeeping", stats->bookkeeping); /* get the summation for all arenas, i == narenas */ CTL_I_GET("stats.arenas.0.pdirty", pdirty, narenas); stats->chunksize = (size_t) 1 << lg_chunk; stats->mapped = mapped; stats->allocated = allocated; stats->waste = active - allocated; stats->page_cache = pdirty * page; stats->bin_unused = compute_bin_unused(narenas); stats->waste -= stats->bin_unused; }
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; }
MOZ_JEMALLOC_API void jemalloc_stats_impl(jemalloc_stats_t *stats) { unsigned narenas; size_t active, allocated, mapped, page, pdirty; CTL_GET("arenas.narenas", narenas); CTL_GET("arenas.page", page); CTL_GET("stats.active", active); CTL_GET("stats.allocated", allocated); CTL_GET("stats.mapped", mapped); /* get the summation for all arenas, i == narenas */ CTL_I_GET("stats.arenas.0.pdirty", pdirty, narenas); stats->allocated = allocated; stats->mapped = mapped; stats->dirty = pdirty * page; stats->committed = active + stats->dirty; }
static void stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i, bool bins, bool large) { unsigned nthreads; const char *dss; 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.page", &page, size_t); CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned); malloc_cprintf(write_cb, cbopaque, "assigned threads: %u\n", nthreads); CTL_I_GET("stats.arenas.0.dss", &dss, const char *); malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n", dss); CTL_I_GET("stats.arenas.0.pactive", &pactive, size_t); CTL_I_GET("stats.arenas.0.pdirty", &pdirty, size_t); CTL_I_GET("stats.arenas.0.npurge", &npurge, uint64_t); CTL_I_GET("stats.arenas.0.nmadvise", &nmadvise, uint64_t); CTL_I_GET("stats.arenas.0.purged", &purged, uint64_t); malloc_cprintf(write_cb, cbopaque, "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s," " %"PRIu64" madvise%s, %"PRIu64" purged\n", pactive, pdirty, npurge, npurge == 1 ? "" : "s", nmadvise, nmadvise == 1 ? "" : "s", purged); malloc_cprintf(write_cb, cbopaque, " allocated nmalloc ndalloc nrequests\n"); CTL_I_GET("stats.arenas.0.small.allocated", &small_allocated, size_t); CTL_I_GET("stats.arenas.0.small.nmalloc", &small_nmalloc, uint64_t); CTL_I_GET("stats.arenas.0.small.ndalloc", &small_ndalloc, uint64_t); CTL_I_GET("stats.arenas.0.small.nrequests", &small_nrequests, uint64_t); malloc_cprintf(write_cb, cbopaque, "small: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", small_allocated, small_nmalloc, small_ndalloc, small_nrequests); CTL_I_GET("stats.arenas.0.large.allocated", &large_allocated, size_t); CTL_I_GET("stats.arenas.0.large.nmalloc", &large_nmalloc, uint64_t); CTL_I_GET("stats.arenas.0.large.ndalloc", &large_ndalloc, uint64_t); CTL_I_GET("stats.arenas.0.large.nrequests", &large_nrequests, uint64_t); malloc_cprintf(write_cb, cbopaque, "large: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", large_allocated, large_nmalloc, large_ndalloc, large_nrequests); malloc_cprintf(write_cb, cbopaque, "total: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", small_allocated + large_allocated, small_nmalloc + large_nmalloc, small_ndalloc + large_ndalloc, small_nrequests + large_nrequests); 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); if (bins) stats_arena_bins_print(write_cb, cbopaque, i); if (large) stats_arena_lruns_print(write_cb, cbopaque, i); }