mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-15 21:27:18 +03:00
Implement prof sample hooks "experimental.hooks.prof_sample(_free)".
The added hooks hooks.prof_sample and hooks.prof_sample_free are intended to allow advanced users to track additional information, to enable new ways of profiling on top of the jemalloc heap profile and sample features. The sample hook is invoked after the allocation and backtracing, and forwards the both the allocation and backtrace to the user hook; the sample_free hook happens before the actual deallocation, and forwards only the ptr and usz to the hook.
This commit is contained in:
parent
a74acb57e8
commit
8580c65f81
7 changed files with 307 additions and 19 deletions
60
src/ctl.c
60
src/ctl.c
|
|
@ -315,6 +315,8 @@ CTL_PROTO(experimental_hooks_install)
|
|||
CTL_PROTO(experimental_hooks_remove)
|
||||
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_safety_check_abort)
|
||||
CTL_PROTO(experimental_thread_activity_callback)
|
||||
CTL_PROTO(experimental_utilization_query)
|
||||
|
|
@ -858,6 +860,8 @@ static const ctl_named_node_t experimental_hooks_node[] = {
|
|||
{NAME("remove"), CTL(experimental_hooks_remove)},
|
||||
{NAME("prof_backtrace"), CTL(experimental_hooks_prof_backtrace)},
|
||||
{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("safety_check_abort"), CTL(experimental_hooks_safety_check_abort)},
|
||||
};
|
||||
|
||||
|
|
@ -3505,6 +3509,62 @@ label_return:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_hooks_prof_sample_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_sample_hook_t old_hook =
|
||||
prof_sample_hook_get();
|
||||
READ(old_hook, prof_sample_hook_t);
|
||||
}
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
prof_sample_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
WRITE(new_hook, prof_sample_hook_t);
|
||||
prof_sample_hook_set(new_hook);
|
||||
}
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_hooks_prof_sample_free_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_sample_free_hook_t old_hook =
|
||||
prof_sample_free_hook_get();
|
||||
READ(old_hook, prof_sample_free_hook_t);
|
||||
}
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
prof_sample_free_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
WRITE(new_hook, prof_sample_free_hook_t);
|
||||
prof_sample_free_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,
|
||||
|
|
|
|||
50
src/prof.c
50
src/prof.c
|
|
@ -78,6 +78,12 @@ atomic_p_t prof_backtrace_hook;
|
|||
/* Logically a prof_dump_hook_t. */
|
||||
atomic_p_t prof_dump_hook;
|
||||
|
||||
/* Logically a prof_sample_hook_t. */
|
||||
atomic_p_t prof_sample_hook;
|
||||
|
||||
/* Logically a prof_sample_free_hook_t. */
|
||||
atomic_p_t prof_sample_free_hook;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
|
|
@ -145,10 +151,20 @@ prof_malloc_sample_object(tsd_t *tsd, const void *ptr, size_t size,
|
|||
if (opt_prof_stats) {
|
||||
prof_stats_inc(tsd, szind, size);
|
||||
}
|
||||
|
||||
/* Sample hook. */
|
||||
prof_sample_hook_t prof_sample_hook = prof_sample_hook_get();
|
||||
if (prof_sample_hook != NULL) {
|
||||
prof_bt_t *bt = &tctx->gctx->bt;
|
||||
pre_reentrancy(tsd, NULL);
|
||||
prof_sample_hook(ptr, size, bt->vec, bt->len);
|
||||
post_reentrancy(tsd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_info_t *prof_info) {
|
||||
prof_free_sampled_object(tsd_t *tsd, const void *ptr, size_t usize,
|
||||
prof_info_t *prof_info) {
|
||||
cassert(config_prof);
|
||||
|
||||
assert(prof_info != NULL);
|
||||
|
|
@ -156,6 +172,16 @@ prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_info_t *prof_info) {
|
|||
assert((uintptr_t)tctx > (uintptr_t)1U);
|
||||
|
||||
szind_t szind = sz_size2index(usize);
|
||||
|
||||
/* Unsample hook. */
|
||||
prof_sample_free_hook_t prof_sample_free_hook =
|
||||
prof_sample_free_hook_get();
|
||||
if (prof_sample_free_hook != NULL) {
|
||||
pre_reentrancy(tsd, NULL);
|
||||
prof_sample_free_hook(ptr, usize);
|
||||
post_reentrancy(tsd);
|
||||
}
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock);
|
||||
|
||||
assert(tctx->cnts.curobjs > 0);
|
||||
|
|
@ -549,6 +575,28 @@ prof_dump_hook_get() {
|
|||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
void
|
||||
prof_sample_hook_set(prof_sample_hook_t hook) {
|
||||
atomic_store_p(&prof_sample_hook, hook, ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
prof_sample_hook_t
|
||||
prof_sample_hook_get() {
|
||||
return (prof_sample_hook_t)atomic_load_p(&prof_sample_hook,
|
||||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
void
|
||||
prof_sample_free_hook_set(prof_sample_free_hook_t hook) {
|
||||
atomic_store_p(&prof_sample_free_hook, hook, ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
prof_sample_free_hook_t
|
||||
prof_sample_free_hook_get() {
|
||||
return (prof_sample_free_hook_t)atomic_load_p(&prof_sample_free_hook,
|
||||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
void
|
||||
prof_boot0(void) {
|
||||
cassert(config_prof);
|
||||
|
|
|
|||
|
|
@ -431,6 +431,8 @@ void
|
|||
prof_hooks_init() {
|
||||
prof_backtrace_hook_set(&prof_backtrace_impl);
|
||||
prof_dump_hook_set(NULL);
|
||||
prof_sample_hook_set(NULL);
|
||||
prof_sample_free_hook_set(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue