Add arena-level name.
An arena-level name can help identify manual arenas.
This commit is contained in:
parent
a0734fd6ee
commit
ba19d2cb78
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
21
src/arena.c
21
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);
|
||||
|
||||
/*
|
||||
|
59
src/ctl.c
59
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)
|
||||
@ -508,7 +509,8 @@ static const ctl_named_node_t arena_i_node[] = {
|
||||
{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("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) {
|
||||
|
13
src/stats.c
13
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",
|
||||
|
@ -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), \
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user