From 54f3351f1f699a2d50f42da7f9a73a8d1a25ea30 Mon Sep 17 00:00:00 2001 From: Yinan Zhang Date: Fri, 21 Aug 2020 14:37:34 -0700 Subject: [PATCH] Add mallctl for prof stats fetching --- src/ctl.c | 170 ++++++++++++++++++++++++++++++++++++++++- test/unit/prof_stats.c | 69 +++++++++++------ 2 files changed, 215 insertions(+), 24 deletions(-) diff --git a/src/ctl.c b/src/ctl.c index 598759cd..a4f1916c 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -12,6 +12,7 @@ #include "jemalloc/internal/prof_data.h" #include "jemalloc/internal/prof_log.h" #include "jemalloc/internal/prof_recent.h" +#include "jemalloc/internal/prof_stats.h" #include "jemalloc/internal/prof_sys.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/util.h" @@ -183,6 +184,12 @@ CTL_PROTO(prof_interval) CTL_PROTO(lg_prof_sample) CTL_PROTO(prof_log_start) CTL_PROTO(prof_log_stop) +CTL_PROTO(prof_stats_bins_i_live) +CTL_PROTO(prof_stats_bins_i_accum) +INDEX_PROTO(prof_stats_bins_i) +CTL_PROTO(prof_stats_lextents_i_live) +CTL_PROTO(prof_stats_lextents_i_accum) +INDEX_PROTO(prof_stats_lextents_i) CTL_PROTO(stats_arenas_i_small_allocated) CTL_PROTO(stats_arenas_i_small_nmalloc) CTL_PROTO(stats_arenas_i_small_ndalloc) @@ -494,6 +501,37 @@ static const ctl_named_node_t arenas_node[] = { {NAME("lookup"), CTL(arenas_lookup)} }; +static const ctl_named_node_t prof_stats_bins_i_node[] = { + {NAME("live"), CTL(prof_stats_bins_i_live)}, + {NAME("accum"), CTL(prof_stats_bins_i_accum)} +}; + +static const ctl_named_node_t super_prof_stats_bins_i_node[] = { + {NAME(""), CHILD(named, prof_stats_bins_i)} +}; + +static const ctl_indexed_node_t prof_stats_bins_node[] = { + {INDEX(prof_stats_bins_i)} +}; + +static const ctl_named_node_t prof_stats_lextents_i_node[] = { + {NAME("live"), CTL(prof_stats_lextents_i_live)}, + {NAME("accum"), CTL(prof_stats_lextents_i_accum)} +}; + +static const ctl_named_node_t super_prof_stats_lextents_i_node[] = { + {NAME(""), CHILD(named, prof_stats_lextents_i)} +}; + +static const ctl_indexed_node_t prof_stats_lextents_node[] = { + {INDEX(prof_stats_lextents_i)} +}; + +static const ctl_named_node_t prof_stats_node[] = { + {NAME("bins"), CHILD(indexed, prof_stats_bins)}, + {NAME("lextents"), CHILD(indexed, prof_stats_lextents)}, +}; + static const ctl_named_node_t prof_node[] = { {NAME("thread_active_init"), CTL(prof_thread_active_init)}, {NAME("active"), CTL(prof_active)}, @@ -504,8 +542,10 @@ static const ctl_named_node_t prof_node[] = { {NAME("interval"), CTL(prof_interval)}, {NAME("lg_sample"), CTL(lg_prof_sample)}, {NAME("log_start"), CTL(prof_log_start)}, - {NAME("log_stop"), CTL(prof_log_stop)} + {NAME("log_stop"), CTL(prof_log_stop)}, + {NAME("stats"), CHILD(named, prof_stats)} }; + static const ctl_named_node_t stats_arenas_i_small_node[] = { {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, @@ -3975,3 +4015,131 @@ experimental_batch_alloc_ctl(tsd_t *tsd, const size_t *mib, label_return: return ret; } + +static int +prof_stats_bins_i_live_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned binind; + prof_stats_t stats; + + if (!(config_prof && opt_prof && opt_prof_stats)) { + ret = ENOENT; + goto label_return; + } + + READONLY(); + MIB_UNSIGNED(binind, 3); + if (binind >= SC_NBINS) { + ret = EINVAL; + goto label_return; + } + prof_stats_get_live(tsd, (szind_t)binind, &stats); + READ(stats, prof_stats_t); + + ret = 0; +label_return: + return ret; +} + +static int +prof_stats_bins_i_accum_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned binind; + prof_stats_t stats; + + if (!(config_prof && opt_prof && opt_prof_stats)) { + ret = ENOENT; + goto label_return; + } + + READONLY(); + MIB_UNSIGNED(binind, 3); + if (binind >= SC_NBINS) { + ret = EINVAL; + goto label_return; + } + prof_stats_get_accum(tsd, (szind_t)binind, &stats); + READ(stats, prof_stats_t); + + ret = 0; +label_return: + return ret; +} + +static const ctl_named_node_t * +prof_stats_bins_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t i) { + if (!(config_prof && opt_prof && opt_prof_stats)) { + return NULL; + } + if (i >= SC_NBINS) { + return NULL; + } + return super_prof_stats_bins_i_node; +} + +static int +prof_stats_lextents_i_live_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned lextent_ind; + prof_stats_t stats; + + if (!(config_prof && opt_prof && opt_prof_stats)) { + ret = ENOENT; + goto label_return; + } + + READONLY(); + MIB_UNSIGNED(lextent_ind, 3); + if (lextent_ind >= SC_NSIZES - SC_NBINS) { + ret = EINVAL; + goto label_return; + } + prof_stats_get_live(tsd, (szind_t)(lextent_ind + SC_NBINS), &stats); + READ(stats, prof_stats_t); + + ret = 0; +label_return: + return ret; +} + +static int +prof_stats_lextents_i_accum_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned lextent_ind; + prof_stats_t stats; + + if (!(config_prof && opt_prof && opt_prof_stats)) { + ret = ENOENT; + goto label_return; + } + + READONLY(); + MIB_UNSIGNED(lextent_ind, 3); + if (lextent_ind >= SC_NSIZES - SC_NBINS) { + ret = EINVAL; + goto label_return; + } + prof_stats_get_accum(tsd, (szind_t)(lextent_ind + SC_NBINS), &stats); + READ(stats, prof_stats_t); + + ret = 0; +label_return: + return ret; +} + +static const ctl_named_node_t * +prof_stats_lextents_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t i) { + if (!(config_prof && opt_prof && opt_prof_stats)) { + return NULL; + } + if (i >= SC_NSIZES - SC_NBINS) { + return NULL; + } + return super_prof_stats_lextents_i_node; +} diff --git a/test/unit/prof_stats.c b/test/unit/prof_stats.c index 555b69e3..123d899c 100644 --- a/test/unit/prof_stats.c +++ b/test/unit/prof_stats.c @@ -1,18 +1,33 @@ #include "test/jemalloc_test.h" -#include "jemalloc/internal/prof_stats.h" - static void test_wrapper(szind_t ind) { #define N_PTRS 3 +#define MALLCTL_STR_LEN 64 assert(opt_prof && opt_prof_stats); - tsd_t *tsd = tsd_fetch(); + char mallctl_live_str[MALLCTL_STR_LEN]; + char mallctl_accum_str[MALLCTL_STR_LEN]; + if (ind < SC_NBINS) { + malloc_snprintf(mallctl_live_str, MALLCTL_STR_LEN, + "prof.stats.bins.%u.live", (unsigned)ind); + malloc_snprintf(mallctl_accum_str, MALLCTL_STR_LEN, + "prof.stats.bins.%u.accum", (unsigned)ind); + } else { + malloc_snprintf(mallctl_live_str, MALLCTL_STR_LEN, + "prof.stats.lextents.%u.live", (unsigned)(ind - SC_NBINS)); + malloc_snprintf(mallctl_accum_str, MALLCTL_STR_LEN, + "prof.stats.lextents.%u.accum", (unsigned)(ind - SC_NBINS)); + } - prof_stats_t live_stats_orig; - prof_stats_get_live(tsd, ind, &live_stats_orig); - prof_stats_t accum_stats_orig; - prof_stats_get_accum(tsd, ind, &accum_stats_orig); + size_t stats_len = 2 * sizeof(uint64_t); + + uint64_t live_stats_orig[2]; + assert_d_eq(mallctl(mallctl_live_str, &live_stats_orig, &stats_len, + NULL, 0), 0, ""); + uint64_t accum_stats_orig[2]; + assert_d_eq(mallctl(mallctl_accum_str, &accum_stats_orig, &stats_len, + NULL, 0), 0, ""); void *ptrs[N_PTRS]; @@ -30,17 +45,19 @@ test_wrapper(szind_t ind) { live_count++; accum_req_sum += sz; accum_count++; - prof_stats_t live_stats; - prof_stats_get_live(tsd, ind, &live_stats); - expect_u64_eq(live_stats.req_sum - live_stats_orig.req_sum, + uint64_t live_stats[2]; + assert_d_eq(mallctl(mallctl_live_str, &live_stats, &stats_len, + NULL, 0), 0, ""); + expect_u64_eq(live_stats[0] - live_stats_orig[0], live_req_sum, ""); - expect_u64_eq(live_stats.count - live_stats_orig.count, + expect_u64_eq(live_stats[1] - live_stats_orig[1], live_count, ""); - prof_stats_t accum_stats; - prof_stats_get_accum(tsd, ind, &accum_stats); - expect_u64_eq(accum_stats.req_sum - accum_stats_orig.req_sum, + uint64_t accum_stats[2]; + assert_d_eq(mallctl(mallctl_accum_str, &accum_stats, &stats_len, + NULL, 0), 0, ""); + expect_u64_eq(accum_stats[0] - accum_stats_orig[0], accum_req_sum, ""); - expect_u64_eq(accum_stats.count - accum_stats_orig.count, + expect_u64_eq(accum_stats[1] - accum_stats_orig[1], accum_count, ""); } @@ -49,19 +66,22 @@ test_wrapper(szind_t ind) { free(ptrs[i]); live_req_sum -= sz; live_count--; - prof_stats_t live_stats; - prof_stats_get_live(tsd, ind, &live_stats); - expect_u64_eq(live_stats.req_sum - live_stats_orig.req_sum, + uint64_t live_stats[2]; + assert_d_eq(mallctl(mallctl_live_str, &live_stats, &stats_len, + NULL, 0), 0, ""); + expect_u64_eq(live_stats[0] - live_stats_orig[0], live_req_sum, ""); - expect_u64_eq(live_stats.count - live_stats_orig.count, + expect_u64_eq(live_stats[1] - live_stats_orig[1], live_count, ""); - prof_stats_t accum_stats; - prof_stats_get_accum(tsd, ind, &accum_stats); - expect_u64_eq(accum_stats.req_sum - accum_stats_orig.req_sum, + uint64_t accum_stats[2]; + assert_d_eq(mallctl(mallctl_accum_str, &accum_stats, &stats_len, + NULL, 0), 0, ""); + expect_u64_eq(accum_stats[0] - accum_stats_orig[0], accum_req_sum, ""); - expect_u64_eq(accum_stats.count - accum_stats_orig.count, + expect_u64_eq(accum_stats[1] - accum_stats_orig[1], accum_count, ""); } +#undef MALLCTL_STR_LEN #undef N_PTRS } @@ -70,6 +90,9 @@ TEST_BEGIN(test_prof_stats) { test_wrapper(0); test_wrapper(1); test_wrapper(2); + test_wrapper(SC_NBINS); + test_wrapper(SC_NBINS + 1); + test_wrapper(SC_NBINS + 2); } TEST_END