mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-05-02 10:07:51 +03:00
Unlike prof_sample which is supported only with profiling mode active, prof_threshold is intended to be an always-supported allocation callback with much less overhead. The usage of the threshold allows performance critical callers to change program execution based on the callback: e.g. drop caches when memory becomes high or to predict the program is about to OOM ahead of time using peak memory watermarks.
This commit is contained in:
parent
ef8e512e29
commit
257e64b968
22 changed files with 246 additions and 0 deletions
31
src/ctl.c
31
src/ctl.c
|
|
@ -154,6 +154,7 @@ CTL_PROTO(opt_prof_active)
|
|||
CTL_PROTO(opt_prof_thread_active_init)
|
||||
CTL_PROTO(opt_prof_bt_max)
|
||||
CTL_PROTO(opt_lg_prof_sample)
|
||||
CTL_PROTO(opt_experimental_lg_prof_threshold)
|
||||
CTL_PROTO(opt_lg_prof_interval)
|
||||
CTL_PROTO(opt_prof_gdump)
|
||||
CTL_PROTO(opt_prof_final)
|
||||
|
|
@ -357,6 +358,7 @@ CTL_PROTO(experimental_hooks_prof_backtrace)
|
|||
CTL_PROTO(experimental_hooks_prof_dump)
|
||||
CTL_PROTO(experimental_hooks_prof_sample)
|
||||
CTL_PROTO(experimental_hooks_prof_sample_free)
|
||||
CTL_PROTO(experimental_hooks_prof_threshold)
|
||||
CTL_PROTO(experimental_hooks_safety_check_abort)
|
||||
CTL_PROTO(experimental_thread_activity_callback)
|
||||
CTL_PROTO(experimental_utilization_query)
|
||||
|
|
@ -539,6 +541,7 @@ static const ctl_named_node_t opt_node[] = {
|
|||
{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
|
||||
{NAME("prof_bt_max"), CTL(opt_prof_bt_max)},
|
||||
{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
|
||||
{NAME("experimental_lg_prof_threshold"), CTL(opt_experimental_lg_prof_threshold)},
|
||||
{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
|
||||
{NAME("prof_gdump"), CTL(opt_prof_gdump)},
|
||||
{NAME("prof_final"), CTL(opt_prof_final)},
|
||||
|
|
@ -965,6 +968,7 @@ static const ctl_named_node_t experimental_hooks_node[] = {
|
|||
{NAME("prof_dump"), CTL(experimental_hooks_prof_dump)},
|
||||
{NAME("prof_sample"), CTL(experimental_hooks_prof_sample)},
|
||||
{NAME("prof_sample_free"), CTL(experimental_hooks_prof_sample_free)},
|
||||
{NAME("prof_threshold"), CTL(experimental_hooks_prof_threshold)},
|
||||
{NAME("safety_check_abort"), CTL(experimental_hooks_safety_check_abort)},
|
||||
};
|
||||
|
||||
|
|
@ -2317,6 +2321,7 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
|
|||
opt_prof_thread_active_init, bool)
|
||||
CTL_RO_NL_CGEN(config_prof, opt_prof_bt_max, opt_prof_bt_max, unsigned)
|
||||
CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
|
||||
CTL_RO_NL_CGEN(config_prof, opt_experimental_lg_prof_threshold, opt_experimental_lg_prof_threshold, size_t)
|
||||
CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
|
||||
CTL_RO_NL_CGEN(config_prof, opt_prof_pid_namespace, opt_prof_pid_namespace,
|
||||
bool)
|
||||
|
|
@ -3778,6 +3783,32 @@ label_return:
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
experimental_hooks_prof_threshold_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (oldp == NULL && newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
if (oldp != NULL) {
|
||||
prof_threshold_hook_t old_hook =
|
||||
prof_threshold_hook_get();
|
||||
READ(old_hook, prof_threshold_hook_t);
|
||||
}
|
||||
if (newp != NULL) {
|
||||
prof_threshold_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
WRITE(new_hook, prof_threshold_hook_t);
|
||||
prof_threshold_hook_set(new_hook);
|
||||
}
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* For integration test purpose only. No plan to move out of experimental. */
|
||||
static int
|
||||
experimental_hooks_safety_check_abort_ctl(tsd_t *tsd, const size_t *mib,
|
||||
|
|
|
|||
|
|
@ -1619,6 +1619,10 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
|
|||
"lg_prof_sample", 0, (sizeof(uint64_t) << 3)
|
||||
- 1, CONF_DONT_CHECK_MIN, CONF_CHECK_MAX,
|
||||
true)
|
||||
CONF_HANDLE_SIZE_T(opt_experimental_lg_prof_threshold,
|
||||
"experimental_lg_prof_threshold", 0, (sizeof(uint64_t) << 3)
|
||||
- 1, CONF_DONT_CHECK_MIN, CONF_CHECK_MAX,
|
||||
true)
|
||||
CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum")
|
||||
CONF_HANDLE_UNSIGNED(opt_prof_bt_max, "prof_bt_max",
|
||||
1, PROF_BT_MAX_LIMIT, CONF_CHECK_MIN, CONF_CHECK_MAX,
|
||||
|
|
|
|||
57
src/prof_threshold.c
Normal file
57
src/prof_threshold.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
||||
|
||||
#include "jemalloc/internal/activity_callback.h"
|
||||
#include "jemalloc/internal/prof_threshold.h"
|
||||
|
||||
#include "jemalloc/internal/prof_externs.h"
|
||||
|
||||
/*
|
||||
* Update every 128MB by default.
|
||||
*/
|
||||
#define PROF_THRESHOLD_LG_WAIT_DEFAULT 27
|
||||
|
||||
/* Logically a prof_threshold_hook_t. */
|
||||
static atomic_p_t prof_threshold_hook;
|
||||
size_t opt_experimental_lg_prof_threshold = PROF_THRESHOLD_LG_WAIT_DEFAULT;
|
||||
|
||||
void
|
||||
prof_threshold_hook_set(prof_threshold_hook_t hook) {
|
||||
atomic_store_p(&prof_threshold_hook, hook, ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
prof_threshold_hook_t
|
||||
prof_threshold_hook_get(void) {
|
||||
return (prof_threshold_hook_t)atomic_load_p(&prof_threshold_hook,
|
||||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
/* Invoke callback for threshold reached */
|
||||
static void
|
||||
prof_threshold_update(tsd_t *tsd) {
|
||||
prof_threshold_hook_t prof_threshold_hook = prof_threshold_hook_get();
|
||||
if (prof_threshold_hook == NULL) {
|
||||
return;
|
||||
}
|
||||
uint64_t alloc = tsd_thread_allocated_get(tsd);
|
||||
uint64_t dalloc = tsd_thread_deallocated_get(tsd);
|
||||
peak_t *peak = tsd_peakp_get(tsd);
|
||||
pre_reentrancy(tsd, NULL);
|
||||
prof_threshold_hook(alloc, dalloc, peak->cur_max);
|
||||
post_reentrancy(tsd);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
prof_threshold_new_event_wait(tsd_t *tsd) {
|
||||
return 1 << opt_experimental_lg_prof_threshold;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
prof_threshold_postponed_event_wait(tsd_t *tsd) {
|
||||
return TE_MIN_START_WAIT;
|
||||
}
|
||||
|
||||
void
|
||||
prof_threshold_event_handler(tsd_t *tsd, uint64_t elapsed) {
|
||||
prof_threshold_update(tsd);
|
||||
}
|
||||
|
|
@ -69,6 +69,11 @@ peak_dalloc_fetch_elapsed(tsd_t *tsd) {
|
|||
return TE_INVALID_ELAPSED;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
prof_threshold_fetch_elapsed(tsd_t *tsd) {
|
||||
return TE_INVALID_ELAPSED;
|
||||
}
|
||||
|
||||
/* Per event facilities done. */
|
||||
|
||||
static bool
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue