summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuangli Dai <gdai@fb.com>2022-09-01 16:42:56 -0700
committerQi Wang <interwq@gmail.com>2022-09-16 15:04:59 -0700
commitba19d2cb78176ef715aca461c7a7a7b2afb35772 (patch)
tree6e0f27ffac4b749ceca3d82968533286139f359d
parenta0734fd6ee326cd2059edbe4bca7092988a63684 (diff)
downloadjemalloc-ba19d2cb78176ef715aca461c7a7a7b2afb35772.tar.gz
Add arena-level name.
An arena-level name can help identify manual arenas.
-rw-r--r--include/jemalloc/internal/arena_externs.h2
-rw-r--r--include/jemalloc/internal/arena_structs.h3
-rw-r--r--include/jemalloc/internal/arena_types.h2
-rw-r--r--src/arena.c21
-rw-r--r--src/ctl.c67
-rw-r--r--src/stats.c13
-rw-r--r--test/include/test/test.h4
-rw-r--r--test/unit/mallctl.c43
8 files changed, 146 insertions, 9 deletions
diff --git a/include/jemalloc/internal/arena_externs.h b/include/jemalloc/internal/arena_externs.h
index e6fceaaf..9f5c1958 100644
--- a/include/jemalloc/internal/arena_externs.h
+++ b/include/jemalloc/internal/arena_externs.h
@@ -88,6 +88,8 @@ ehooks_t *arena_get_ehooks(arena_t *arena);
extent_hooks_t *arena_set_extent_hooks(tsd_t *tsd, arena_t *arena,
extent_hooks_t *extent_hooks);
bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);
+void arena_name_get(arena_t *arena, char *name);
+void arena_name_set(arena_t *arena, const char *name);
ssize_t arena_dirty_decay_ms_default_get(void);
bool arena_dirty_decay_ms_default_set(ssize_t decay_ms);
ssize_t arena_muzzy_decay_ms_default_get(void);
diff --git a/include/jemalloc/internal/arena_structs.h b/include/jemalloc/internal/arena_structs.h
index e2a5a408..e6868fce 100644
--- a/include/jemalloc/internal/arena_structs.h
+++ b/include/jemalloc/internal/arena_structs.h
@@ -91,6 +91,9 @@ struct arena_s {
/* Used to determine uptime. Read-only after initialization. */
nstime_t create_time;
+ /* The name of the arena. */
+ char name[ARENA_NAME_LEN];
+
/*
* The arena is allocated alongside its bins; really this is a
* dynamically sized array determined by the binshard settings.
diff --git a/include/jemalloc/internal/arena_types.h b/include/jemalloc/internal/arena_types.h
index d0e12917..45eec69f 100644
--- a/include/jemalloc/internal/arena_types.h
+++ b/include/jemalloc/internal/arena_types.h
@@ -8,6 +8,8 @@
#define MUZZY_DECAY_MS_DEFAULT (0)
/* Number of event ticks between time checks. */
#define ARENA_DECAY_NTICKS_PER_UPDATE 1000
+/* Maximum length of the arena name. */
+#define ARENA_NAME_LEN 32
typedef struct arena_decay_s arena_decay_t;
typedef struct arena_s arena_t;
diff --git a/src/arena.c b/src/arena.c
index 1ab2775e..25ab41af 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -1547,6 +1547,22 @@ arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) {
return false;
}
+void
+arena_name_get(arena_t *arena, char *name) {
+ char *end = (char *)memchr((void *)arena->name, '\0', ARENA_NAME_LEN);
+ assert(end != NULL);
+ size_t len = (uintptr_t)end - (uintptr_t)arena->name + 1;
+ assert(len > 0 && len <= ARENA_NAME_LEN);
+
+ strncpy(name, arena->name, len);
+}
+
+void
+arena_name_set(arena_t *arena, const char *name) {
+ strncpy(arena->name, name, ARENA_NAME_LEN);
+ arena->name[ARENA_NAME_LEN - 1] = '\0';
+}
+
ssize_t
arena_dirty_decay_ms_default_get(void) {
return atomic_load_zd(&dirty_decay_ms_default, ATOMIC_RELAXED);
@@ -1670,6 +1686,11 @@ arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) {
arena_set(ind, arena);
arena->ind = ind;
+ /* Init the name. */
+ malloc_snprintf(arena->name, sizeof(arena->name), "%s_%u",
+ arena_is_auto(arena) ? "auto" : "manual", arena->ind);
+ arena->name[ARENA_NAME_LEN - 1] = '\0';
+
nstime_init_update(&arena->create_time);
/*
diff --git a/src/ctl.c b/src/ctl.c
index 6b03f986..acf5d366 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -170,6 +170,7 @@ CTL_PROTO(arena_i_dirty_decay_ms)
CTL_PROTO(arena_i_muzzy_decay_ms)
CTL_PROTO(arena_i_extent_hooks)
CTL_PROTO(arena_i_retain_grow_limit)
+CTL_PROTO(arena_i_name)
INDEX_PROTO(arena_i)
CTL_PROTO(arenas_bin_i_size)
CTL_PROTO(arenas_bin_i_nregs)
@@ -504,11 +505,12 @@ static const ctl_named_node_t arena_i_node[] = {
* Undocumented for now, since we anticipate an arena API in flux after
* we cut the last 5-series release.
*/
- {NAME("oversize_threshold"), CTL(arena_i_oversize_threshold)},
- {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)},
- {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)},
- {NAME("extent_hooks"), CTL(arena_i_extent_hooks)},
- {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)}
+ {NAME("oversize_threshold"), CTL(arena_i_oversize_threshold)},
+ {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)},
+ {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)},
+ {NAME("extent_hooks"), CTL(arena_i_extent_hooks)},
+ {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)},
+ {NAME("name"), CTL(arena_i_name)}
};
static const ctl_named_node_t super_arena_i_node[] = {
{NAME(""), CHILD(named, arena_i)}
@@ -2983,6 +2985,61 @@ label_return:
return ret;
}
+/*
+ * When writing, newp should point to a char array storing the name to be set.
+ * A name longer than ARENA_NAME_LEN will be arbitrarily cut. When reading,
+ * oldp should point to a char array whose length is no shorter than
+ * ARENA_NAME_LEN or the length of the name when it was set.
+ */
+static int
+arena_i_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
+ void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
+ int ret;
+ unsigned arena_ind;
+ char *name;
+
+ malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
+ MIB_UNSIGNED(arena_ind, 1);
+ if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind >=
+ ctl_arenas->narenas) {
+ ret = EINVAL;
+ goto label_return;
+ }
+ arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
+ if (arena == NULL) {
+ ret = EFAULT;
+ goto label_return;
+ }
+
+ if (oldp != NULL && oldlenp != NULL) {
+ /*
+ * Read the arena name. When reading, the input oldp should
+ * point to an array with a length no shorter than
+ * ARENA_NAME_LEN or the length when it was set.
+ */
+ if (*oldlenp != sizeof(char *)) {
+ ret = EINVAL;
+ goto label_return;
+ }
+ name = *(char **)oldp;
+ arena_name_get(arena, name);
+ }
+
+ if (newp != NULL) {
+ /* Write the arena name. */
+ WRITE(name, char *);
+ if (name == NULL) {
+ ret = EINVAL;
+ goto label_return;
+ }
+ arena_name_set(arena, name);
+ }
+ ret = 0;
+label_return:
+ malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
+ return ret;
+}
+
static const ctl_named_node_t *
arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
size_t i) {
diff --git a/src/stats.c b/src/stats.c
index 5bb1a346..701a6c86 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -42,15 +42,18 @@ const char *arena_mutex_names[mutex_prof_num_arena_mutexes] = {
assert(miblen_new == miblen + 1); \
} while (0)
-#define CTL_M2_GET(n, i, v, t) do { \
+#define CTL_MIB_GET(n, i, v, t, ind) do { \
size_t mib[CTL_MAX_DEPTH]; \
size_t miblen = sizeof(mib) / sizeof(size_t); \
size_t sz = sizeof(t); \
xmallctlnametomib(n, mib, &miblen); \
- mib[2] = (i); \
+ mib[(ind)] = (i); \
xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \
} while (0)
+#define CTL_M1_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 1)
+#define CTL_M2_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 2)
+
/******************************************************************************/
/* Data. */
@@ -1042,6 +1045,8 @@ JEMALLOC_COLD
static void
stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
bool mutex, bool extents, bool hpa) {
+ char name[ARENA_NAME_LEN];
+ char *namep = name;
unsigned nthreads;
const char *dss;
ssize_t dirty_decay_ms, muzzy_decay_ms;
@@ -1059,6 +1064,10 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
uint64_t uptime;
CTL_GET("arenas.page", &page, size_t);
+ if (i != MALLCTL_ARENAS_ALL && i != MALLCTL_ARENAS_DESTROYED) {
+ CTL_M1_GET("arena.0.name", i, (void *)&namep, const char *);
+ emitter_kv(emitter, "name", "name", emitter_type_string, &namep);
+ }
CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned);
emitter_kv(emitter, "nthreads", "assigned threads",
diff --git a/test/include/test/test.h b/test/include/test/test.h
index d4b65912..54610dab 100644
--- a/test/include/test/test.h
+++ b/test/include/test/test.h
@@ -266,7 +266,7 @@
#define expect_false(a, ...) expect_b_eq(a, false, __VA_ARGS__)
#define verify_str_eq(may_abort, a, b, ...) do { \
- if (strcmp((a), (b))) { \
+ if (strcmp((a), (b)) != 0) { \
char prefix[ASSERT_BUFSIZE]; \
char message[ASSERT_BUFSIZE]; \
malloc_snprintf(prefix, sizeof(prefix), \
@@ -284,7 +284,7 @@
} while (0)
#define verify_str_ne(may_abort, a, b, ...) do { \
- if (!strcmp((a), (b))) { \
+ if (strcmp((a), (b)) == 0) { \
char prefix[ASSERT_BUFSIZE]; \
char message[ASSERT_BUFSIZE]; \
malloc_snprintf(prefix, sizeof(prefix), \
diff --git a/test/unit/mallctl.c b/test/unit/mallctl.c
index 14fe7993..244d4c96 100644
--- a/test/unit/mallctl.c
+++ b/test/unit/mallctl.c
@@ -711,6 +711,48 @@ TEST_BEGIN(test_arena_i_dss) {
}
TEST_END
+TEST_BEGIN(test_arena_i_name) {
+ unsigned arena_ind;
+ size_t ind_sz = sizeof(arena_ind);
+ size_t mib[3];
+ size_t miblen;
+ char name_old[ARENA_NAME_LEN];
+ char *name_oldp = name_old;
+ size_t sz = sizeof(name_oldp);
+ char default_name[ARENA_NAME_LEN];
+ const char *name_new = "test name";
+ const char *super_long_name = "A name longer than ARENA_NAME_LEN";
+ size_t super_long_name_len = strlen(super_long_name);
+ assert(super_long_name_len > ARENA_NAME_LEN);
+
+ miblen = sizeof(mib)/sizeof(size_t);
+ expect_d_eq(mallctlnametomib("arena.0.name", mib, &miblen), 0,
+ "Unexpected mallctlnametomib() error");
+
+ expect_d_eq(mallctl("arenas.create", (void *)&arena_ind, &ind_sz, NULL,
+ 0), 0, "Unexpected mallctl() failure");
+ mib[1] = arena_ind;
+
+ malloc_snprintf(default_name, sizeof(default_name), "manual_%u",
+ arena_ind);
+ expect_d_eq(mallctlbymib(mib, miblen, (void *)&name_oldp, &sz,
+ (void *)&name_new, sizeof(name_new)), 0,
+ "Unexpected mallctl() failure");
+ expect_str_eq(name_old, default_name,
+ "Unexpected default value for arena name");
+
+ expect_d_eq(mallctlbymib(mib, miblen, (void *)&name_oldp, &sz,
+ (void *)&super_long_name, sizeof(super_long_name)), 0,
+ "Unexpected mallctl() failure");
+ expect_str_eq(name_old, name_new, "Unexpected value for arena name");
+
+ expect_d_eq(mallctlbymib(mib, miblen, (void *)&name_oldp, &sz,
+ NULL, 0), 0, "Unexpected mallctl() failure");
+ int cmp = strncmp(name_old, super_long_name, ARENA_NAME_LEN - 1);
+ expect_true(cmp == 0, "Unexpected value for long arena name ");
+}
+TEST_END
+
TEST_BEGIN(test_arena_i_retain_grow_limit) {
size_t old_limit, new_limit, default_limit;
size_t mib[3];
@@ -1258,6 +1300,7 @@ main(void) {
test_arena_i_purge,
test_arena_i_decay,
test_arena_i_dss,
+ test_arena_i_name,
test_arena_i_retain_grow_limit,
test_arenas_dirty_decay_ms,
test_arenas_muzzy_decay_ms,