Add experimental.arenas.i.pactivep.
The new experimental mallctl exposes the arena pactive counter to applications, which allows fast read w/o going through the mallctl / epoch steps. This is particularly useful when frequent balancing is required, e.g. when having multiple manual arenas, and threads are multiplexed to them based on usage.
This commit is contained in:
parent
c92ac30601
commit
e13cf65a5f
89
src/ctl.c
89
src/ctl.c
@ -225,6 +225,8 @@ CTL_PROTO(experimental_hooks_install)
|
||||
CTL_PROTO(experimental_hooks_remove)
|
||||
CTL_PROTO(experimental_utilization_query)
|
||||
CTL_PROTO(experimental_utilization_batch_query)
|
||||
CTL_PROTO(experimental_arenas_i_pactivep)
|
||||
INDEX_PROTO(experimental_arenas_i)
|
||||
|
||||
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
||||
CTL_PROTO(stats_##n##_num_ops) \
|
||||
@ -588,19 +590,31 @@ static const ctl_named_node_t stats_node[] = {
|
||||
{NAME("arenas"), CHILD(indexed, stats_arenas)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t hooks_node[] = {
|
||||
static const ctl_named_node_t experimental_hooks_node[] = {
|
||||
{NAME("install"), CTL(experimental_hooks_install)},
|
||||
{NAME("remove"), CTL(experimental_hooks_remove)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t utilization_node[] = {
|
||||
static const ctl_named_node_t experimental_utilization_node[] = {
|
||||
{NAME("query"), CTL(experimental_utilization_query)},
|
||||
{NAME("batch_query"), CTL(experimental_utilization_batch_query)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t experimental_arenas_i_node[] = {
|
||||
{NAME("pactivep"), CTL(experimental_arenas_i_pactivep)}
|
||||
};
|
||||
static const ctl_named_node_t super_experimental_arenas_i_node[] = {
|
||||
{NAME(""), CHILD(named, experimental_arenas_i)}
|
||||
};
|
||||
|
||||
static const ctl_indexed_node_t experimental_arenas_node[] = {
|
||||
{INDEX(experimental_arenas_i)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t experimental_node[] = {
|
||||
{NAME("hooks"), CHILD(named, hooks)},
|
||||
{NAME("utilization"), CHILD(named, utilization)}
|
||||
{NAME("hooks"), CHILD(named, experimental_hooks)},
|
||||
{NAME("utilization"), CHILD(named, experimental_utilization)},
|
||||
{NAME("arenas"), CHILD(indexed, experimental_arenas)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t root_node[] = {
|
||||
@ -3068,15 +3082,23 @@ stats_arenas_i_extents_j_index(tsdn_t *tsdn, const size_t *mib,
|
||||
return super_stats_arenas_i_extents_j_node;
|
||||
}
|
||||
|
||||
static bool
|
||||
ctl_arenas_i_verify(size_t i) {
|
||||
size_t a = arenas_i2a_impl(i, true, true);
|
||||
if (a == UINT_MAX || !ctl_arenas->arenas[a]->initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const ctl_named_node_t *
|
||||
stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
|
||||
size_t miblen, size_t i) {
|
||||
const ctl_named_node_t *ret;
|
||||
size_t a;
|
||||
|
||||
malloc_mutex_lock(tsdn, &ctl_mtx);
|
||||
a = arenas_i2a_impl(i, true, true);
|
||||
if (a == UINT_MAX || !ctl_arenas->arenas[a]->initialized) {
|
||||
if (ctl_arenas_i_verify(i)) {
|
||||
ret = NULL;
|
||||
goto label_return;
|
||||
}
|
||||
@ -3351,3 +3373,56 @@ experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib,
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const ctl_named_node_t *
|
||||
experimental_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
|
||||
size_t miblen, size_t i) {
|
||||
const ctl_named_node_t *ret;
|
||||
|
||||
malloc_mutex_lock(tsdn, &ctl_mtx);
|
||||
if (ctl_arenas_i_verify(i)) {
|
||||
ret = NULL;
|
||||
goto label_return;
|
||||
}
|
||||
ret = super_experimental_arenas_i_node;
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsdn, &ctl_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_arenas_i_pactivep_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
if (!config_stats) {
|
||||
return ENOENT;
|
||||
}
|
||||
if (oldp == NULL || oldlenp == NULL || *oldlenp != sizeof(size_t *)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
unsigned arena_ind;
|
||||
arena_t *arena;
|
||||
int ret;
|
||||
size_t *pactivep;
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
READONLY();
|
||||
MIB_UNSIGNED(arena_ind, 2);
|
||||
if (arena_ind < narenas_total_get() && (arena =
|
||||
arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
|
||||
#if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) || \
|
||||
defined(JEMALLOC_GCC_SYNC_ATOMICS) || defined(_MSC_VER)
|
||||
/* Expose the underlying counter for fast read. */
|
||||
pactivep = (size_t *)&(arena->nactive.repr);
|
||||
READ(pactivep, size_t *);
|
||||
ret = 0;
|
||||
#else
|
||||
ret = EFAULT;
|
||||
#endif
|
||||
} else {
|
||||
ret = EFAULT;
|
||||
}
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user