mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 13:13:06 +00:00
Add support for namespace pids in heap profile names
This change adds support for writing pid namespaces to the filename of a heap profile. When running with namespaces pids may reused across namespaces and if mounts are shared where profiles are written there is not a great way to differentiate profiles between pids. Signed-off-by: Daniel Hodges <hodges.daniel.scott@gmail.com> Signed-off-by: Daniel Hodges <hodgesd@fb.com>
This commit is contained in:
@@ -1514,6 +1514,23 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
|||||||
by default.</para></listitem>
|
by default.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="opt.prof_pid_namespace">
|
||||||
|
<term>
|
||||||
|
<mallctl>opt.prof_pid_namespace</mallctl>
|
||||||
|
(<type>bool</type>)
|
||||||
|
<literal>r-</literal>
|
||||||
|
[<option>--enable-prof</option>]
|
||||||
|
</term>
|
||||||
|
<listitem><para>Enable adding the pid namespace to the profile
|
||||||
|
filename. Profiles are dumped to files named according to the pattern
|
||||||
|
<filename><prefix>.<pid_namespace>.<pid>.<seq>.i<iseq>.heap</filename>,
|
||||||
|
where <literal><prefix></literal> is controlled by the <link
|
||||||
|
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> and
|
||||||
|
<link linkend="prof.prefix"><mallctl>prof.prefix</mallctl></link>
|
||||||
|
options.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="opt.lg_prof_interval">
|
<varlistentry id="opt.lg_prof_interval">
|
||||||
<term>
|
<term>
|
||||||
<mallctl>opt.lg_prof_interval</mallctl>
|
<mallctl>opt.lg_prof_interval</mallctl>
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ extern char opt_prof_prefix[
|
|||||||
1];
|
1];
|
||||||
extern bool opt_prof_unbias;
|
extern bool opt_prof_unbias;
|
||||||
|
|
||||||
|
/* Include pid namespace in profile file names. */
|
||||||
|
extern bool opt_prof_pid_namespace;
|
||||||
|
|
||||||
/* For recording recent allocations */
|
/* For recording recent allocations */
|
||||||
extern ssize_t opt_prof_recent_alloc_max;
|
extern ssize_t opt_prof_recent_alloc_max;
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ CTL_PROTO(opt_prof_final)
|
|||||||
CTL_PROTO(opt_prof_leak)
|
CTL_PROTO(opt_prof_leak)
|
||||||
CTL_PROTO(opt_prof_leak_error)
|
CTL_PROTO(opt_prof_leak_error)
|
||||||
CTL_PROTO(opt_prof_accum)
|
CTL_PROTO(opt_prof_accum)
|
||||||
|
CTL_PROTO(opt_prof_pid_namespace)
|
||||||
CTL_PROTO(opt_prof_recent_alloc_max)
|
CTL_PROTO(opt_prof_recent_alloc_max)
|
||||||
CTL_PROTO(opt_prof_stats)
|
CTL_PROTO(opt_prof_stats)
|
||||||
CTL_PROTO(opt_prof_sys_thread_name)
|
CTL_PROTO(opt_prof_sys_thread_name)
|
||||||
@@ -507,6 +508,7 @@ static const ctl_named_node_t opt_node[] = {
|
|||||||
{NAME("prof_leak"), CTL(opt_prof_leak)},
|
{NAME("prof_leak"), CTL(opt_prof_leak)},
|
||||||
{NAME("prof_leak_error"), CTL(opt_prof_leak_error)},
|
{NAME("prof_leak_error"), CTL(opt_prof_leak_error)},
|
||||||
{NAME("prof_accum"), CTL(opt_prof_accum)},
|
{NAME("prof_accum"), CTL(opt_prof_accum)},
|
||||||
|
{NAME("prof_pid_namespace"), CTL(opt_prof_pid_namespace)},
|
||||||
{NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)},
|
{NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)},
|
||||||
{NAME("prof_stats"), CTL(opt_prof_stats)},
|
{NAME("prof_stats"), CTL(opt_prof_stats)},
|
||||||
{NAME("prof_sys_thread_name"), CTL(opt_prof_sys_thread_name)},
|
{NAME("prof_sys_thread_name"), CTL(opt_prof_sys_thread_name)},
|
||||||
@@ -2226,6 +2228,8 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
|
|||||||
CTL_RO_NL_CGEN(config_prof, opt_prof_bt_max, opt_prof_bt_max, unsigned)
|
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_lg_prof_sample, opt_lg_prof_sample, size_t)
|
||||||
CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
|
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)
|
||||||
CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
|
CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
|
||||||
CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
|
CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
|
||||||
CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
|
CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
|
||||||
|
|||||||
@@ -1628,6 +1628,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
|
|||||||
CONF_HANDLE_BOOL(opt_prof_leak_error,
|
CONF_HANDLE_BOOL(opt_prof_leak_error,
|
||||||
"prof_leak_error")
|
"prof_leak_error")
|
||||||
CONF_HANDLE_BOOL(opt_prof_log, "prof_log")
|
CONF_HANDLE_BOOL(opt_prof_log, "prof_log")
|
||||||
|
CONF_HANDLE_BOOL(opt_prof_pid_namespace, "prof_pid_namespace")
|
||||||
CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max,
|
CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max,
|
||||||
"prof_recent_alloc_max", -1, SSIZE_MAX)
|
"prof_recent_alloc_max", -1, SSIZE_MAX)
|
||||||
CONF_HANDLE_BOOL(opt_prof_stats, "prof_stats")
|
CONF_HANDLE_BOOL(opt_prof_stats, "prof_stats")
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ bool opt_prof_final = false;
|
|||||||
bool opt_prof_leak = false;
|
bool opt_prof_leak = false;
|
||||||
bool opt_prof_leak_error = false;
|
bool opt_prof_leak_error = false;
|
||||||
bool opt_prof_accum = false;
|
bool opt_prof_accum = false;
|
||||||
|
bool opt_prof_pid_namespace = false;
|
||||||
char opt_prof_prefix[PROF_DUMP_FILENAME_LEN];
|
char opt_prof_prefix[PROF_DUMP_FILENAME_LEN];
|
||||||
bool opt_prof_sys_thread_name = false;
|
bool opt_prof_sys_thread_name = false;
|
||||||
bool opt_prof_unbias = true;
|
bool opt_prof_unbias = true;
|
||||||
|
|||||||
@@ -484,6 +484,41 @@ prof_getpid(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
prof_get_pid_namespace() {
|
||||||
|
long ret = 0;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
// Not supported, do nothing.
|
||||||
|
#else
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
const char* linkname =
|
||||||
|
# if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
"/proc/curproc/ns/pid"
|
||||||
|
# else
|
||||||
|
"/proc/self/ns/pid"
|
||||||
|
# endif
|
||||||
|
;
|
||||||
|
ssize_t linklen =
|
||||||
|
# ifndef JEMALLOC_READLINKAT
|
||||||
|
readlink(linkname, buf, PATH_MAX)
|
||||||
|
# else
|
||||||
|
readlinkat(AT_FDCWD, linkname, buf, PATH_MAX)
|
||||||
|
# endif
|
||||||
|
;
|
||||||
|
|
||||||
|
// namespace string is expected to be like pid:[4026531836]
|
||||||
|
if (linklen > 0) {
|
||||||
|
// Trim the trailing "]"
|
||||||
|
buf[linklen-1] = '\0';
|
||||||
|
char* index = strtok(buf, "pid:[");
|
||||||
|
ret = atol(index);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This buffer is rather large for stack allocation, so use a single buffer for
|
* This buffer is rather large for stack allocation, so use a single buffer for
|
||||||
* all profile dumps; protected by prof_dump_mtx.
|
* all profile dumps; protected by prof_dump_mtx.
|
||||||
@@ -713,15 +748,30 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) {
|
|||||||
const char *prefix = prof_prefix_get(tsd_tsdn(tsd));
|
const char *prefix = prof_prefix_get(tsd_tsdn(tsd));
|
||||||
|
|
||||||
if (vseq != VSEQ_INVALID) {
|
if (vseq != VSEQ_INVALID) {
|
||||||
/* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
|
if (opt_prof_pid_namespace) {
|
||||||
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
/* "<prefix>.<pid_namespace>.<pid>.<seq>.v<vseq>.heap" */
|
||||||
"%s.%d.%"FMTu64".%c%"FMTu64".heap", prefix, prof_getpid(),
|
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
||||||
prof_dump_seq, v, vseq);
|
"%s.%ld.%d.%"FMTu64".%c%"FMTu64".heap", prefix,
|
||||||
|
prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v,
|
||||||
|
vseq);
|
||||||
|
} else {
|
||||||
|
/* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
|
||||||
|
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
||||||
|
"%s.%d.%"FMTu64".%c%"FMTu64".heap", prefix, prof_getpid(),
|
||||||
|
prof_dump_seq, v, vseq);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* "<prefix>.<pid>.<seq>.<v>.heap" */
|
if (opt_prof_pid_namespace) {
|
||||||
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
/* "<prefix>.<pid_namespace>.<pid>.<seq>.<v>.heap" */
|
||||||
"%s.%d.%"FMTu64".%c.heap", prefix, prof_getpid(),
|
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
||||||
prof_dump_seq, v);
|
"%s.%ld.%d.%"FMTu64".%c.heap", prefix,
|
||||||
|
prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v);
|
||||||
|
} else {
|
||||||
|
/* "<prefix>.<pid>.<seq>.<v>.heap" */
|
||||||
|
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
|
||||||
|
"%s.%d.%"FMTu64".%c.heap", prefix, prof_getpid(),
|
||||||
|
prof_dump_seq, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prof_dump_seq++;
|
prof_dump_seq++;
|
||||||
}
|
}
|
||||||
@@ -729,8 +779,14 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) {
|
|||||||
void
|
void
|
||||||
prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind) {
|
prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind) {
|
||||||
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
|
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
|
||||||
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
|
if (opt_prof_pid_namespace) {
|
||||||
"%s.%d.%"FMTu64".json", prof_prefix_get(tsdn), prof_getpid(), ind);
|
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
|
||||||
|
"%s.%ld.%d.%"FMTu64".json", prof_prefix_get(tsdn),
|
||||||
|
prof_get_pid_namespace(), prof_getpid(), ind);
|
||||||
|
} else {
|
||||||
|
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
|
||||||
|
"%s.%d.%"FMTu64".json", prof_prefix_get(tsdn), prof_getpid(), ind);
|
||||||
|
}
|
||||||
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
|
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ TEST_BEGIN(test_mallctl_opt) {
|
|||||||
TEST_MALLCTL_OPT(unsigned, prof_bt_max, prof);
|
TEST_MALLCTL_OPT(unsigned, prof_bt_max, prof);
|
||||||
TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
|
TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
|
||||||
TEST_MALLCTL_OPT(bool, prof_accum, prof);
|
TEST_MALLCTL_OPT(bool, prof_accum, prof);
|
||||||
|
TEST_MALLCTL_OPT(bool, prof_pid_namespace, prof);
|
||||||
TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
|
TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
|
||||||
TEST_MALLCTL_OPT(bool, prof_gdump, prof);
|
TEST_MALLCTL_OPT(bool, prof_gdump, prof);
|
||||||
TEST_MALLCTL_OPT(bool, prof_final, prof);
|
TEST_MALLCTL_OPT(bool, prof_final, prof);
|
||||||
|
|||||||
Reference in New Issue
Block a user