Re: [PATCH v3 2/7] libdtrace: share vmlinux BTF/CTF globally to support faster startup
Alan Maguire <[email protected]> Thu, 23 Jul 2026 14:22:10 +0100
| Newsgroups | dev.linux.lists.dtrace |
|---|---|
| Message-ID | <[email protected]> |
On 22/07/2026 22:21, Kris Van Hees wrote: > On Tue, Jul 21, 2026 at 04:24:46PM +0100, Alan Maguire wrote: >> In a multiple DTrace session per process environment, it makes sense >> to avoid doing expensive operations like reading in vmlinux BTF and >> converting it to CTF more than once. Shared (vmlinux) BTF and CTF >> generated from it are shared and reference-counted globally here >> to cut down on cost. With this change, we can launch ~1 DTrace >> session per second. > > There are a few logic issues here that need to be address I think. Since we > do support -xbtfpath and DTRACE_OPT_BTFPATH, hardcoding the path to vmlinux > is an issue. > > Ideally, this code should allow for both shared and private type data. I.e. > if a -xbtfpath opion is given or DTRACE_OPT_BTFPATH is set, then the instance > will use a private copy. Otherwise, it will use a shared one that is sourced > from the system default. > > More fancy would be to allow multiple shared ones, keyed by full path (and > considering that it will be very very rare to ever have more than one). > > So, I would suggest going with the first option (shared and private), and the > close code can check whether dtp->dt_shared_btf == dt_shared_btf. If so, it > is a hared one so handle it that way. If not, clean up as a private copy. > good catch, thanks! I'll do this in the next version. >> Signed-off-by: Alan Maguire <[email protected]> >> --- >> libdtrace/dt_btf.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- >> libdtrace/dt_btf.h | 1 + >> libdtrace/dt_open.c | 5 +--- >> 3 files changed, 60 insertions(+), 7 deletions(-) >> >> diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c >> index 1f793397..e46336f9 100644 >> --- a/libdtrace/dt_btf.c >> +++ b/libdtrace/dt_btf.c >> @@ -693,6 +693,9 @@ dt_btf_to_ctf(dtrace_hdl_t *dtp, dt_module_t *dmp, dt_btf_t *btf) >> ctf_dict_t *ctf; >> ctf_encoding_t enc = { CTF_INT_SIGNED, 0, 0 }; >> >> + if (dmp == NULL && dtp->dt_shared_ctf) >> + return dtp->dt_shared_ctf; >> + >> ctf = ctf_create(&dtp->dt_ctferr); >> if (ctf == NULL) >> return NULL; >> @@ -764,6 +767,56 @@ out: >> } >> #endif >> >> +static dt_btf_t *dt_shared_btf = NULL; >> +static ctf_dict_t *dt_shared_ctf = NULL; >> +static pthread_mutex_t dt_shared_mutex = PTHREAD_MUTEX_INITIALIZER; >> +static int dt_shared_refcnt = 0; >> + >> +static int >> +dt_shared_get(dtrace_hdl_t *dtp, dt_module_t *dmp) >> +{ >> + pthread_mutex_lock(&dt_shared_mutex); >> + if (!dt_shared_btf) >> + dt_shared_btf = dt_btf_load_file(dtp, "/sys/kernel/btf/vmlinux"); >> + if (dt_shared_btf) { >> + dt_shared_refcnt++; >> + dtp->dt_shared_btf = dmp->dm_btf = dt_shared_btf; >> +#ifdef HAVE_LIBCTF >> + if (!dt_shared_ctf) { >> + ctf_dict_t *ctf = dt_btf_to_ctf(dtp, NULL, dt_shared_btf); >> + >> + if (ctf) >> + dtp->dt_shared_ctf = dt_shared_ctf = dmp->dm_ctfp = ctf; >> + } else { >> + dtp->dt_shared_ctf = dmp->dm_ctfp = dt_shared_ctf; >> + } >> +#endif >> + } >> + pthread_mutex_unlock(&dt_shared_mutex); >> + if (!dt_shared_btf) >> + return -1; >> + return 0; >> +} >> + >> +void >> +dt_shared_put(dtrace_hdl_t *dtp) >> +{ >> + pthread_mutex_lock(&dt_shared_mutex); >> + if (dtp->dt_shared_btf && dtp->dt_shared_btf == dt_shared_btf) { >> + if (--dt_shared_refcnt == 0) { >> + dt_btf_destroy(dtp, dtp->dt_shared_btf); >> + dtp->dt_shared_btf = dt_shared_btf = NULL; >> + } >> + } >> +#ifdef HAVE_LIBCTF >> + if (dt_shared_refcnt == 0) { >> + ctf_close(dtp->dt_shared_ctf); >> + dtp->dt_shared_ctf = dt_shared_ctf = NULL; >> + } >> +#endif >> + pthread_mutex_unlock(&dt_shared_mutex); >> +} >> + >> dt_btf_t * >> dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp) >> { >> @@ -774,6 +827,11 @@ dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp) >> if (dmp->dm_btf) >> return dmp->dm_btf; >> >> + if (strcmp(dmp->dm_name, "vmlinux") == 0) { >> + if (dt_shared_get(dtp, dmp) == 0) >> + return dmp->dm_btf; >> + } >> + >> /* >> * Default: /sys/kernel/btf/<module> >> * If "none", disable BTF. >> @@ -792,9 +850,6 @@ dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp) >> btf = dt_btf_load_file(dtp, fn); >> free(fn); >> >> - if (btf && !dtp->dt_shared_btf && strcmp(dmp->dm_name, "vmlinux") == 0) >> - dtp->dt_shared_btf = btf; >> - >> return dmp->dm_btf = btf; >> } >> >> diff --git a/libdtrace/dt_btf.h b/libdtrace/dt_btf.h >> index 2c921a03..b1ed2b65 100644 >> --- a/libdtrace/dt_btf.h >> +++ b/libdtrace/dt_btf.h >> @@ -18,6 +18,7 @@ typedef struct dt_btf dt_btf_t; >> typedef struct bpf_btf_info btf_info_t; >> >> extern void dt_btf_destroy(dtrace_hdl_t *, dt_btf_t *); >> +extern void dt_shared_put(dtrace_hdl_t *); >> extern dt_btf_t *dt_btf_load_module(dtrace_hdl_t *, dt_module_t *); >> extern ctf_dict_t *dt_btf_module_ctf(dtrace_hdl_t *, dt_module_t *); >> extern const char *dt_btf_get_string(dtrace_hdl_t *, const dt_btf_t *, >> diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c >> index 30b8758d..352cec49 100644 >> --- a/libdtrace/dt_open.c >> +++ b/libdtrace/dt_open.c >> @@ -1299,10 +1299,7 @@ dtrace_close(dtrace_hdl_t *dtp) >> dt_htab_destroy(dtp->dt_mods); >> dt_htab_destroy(dtp->dt_kernpaths); >> >> - if (dtp->dt_shared_btf != NULL) >> - dt_btf_destroy(dtp, dtp->dt_shared_btf); >> - if (dtp->dt_shared_ctf != NULL) >> - ctf_close(dtp->dt_shared_ctf); >> + dt_shared_put(dtp); >> if (dtp->dt_ctfa != NULL) >> ctf_arc_close(dtp->dt_ctfa); >> >> -- >> 2.43.5 >> >> >>