[DTrace-devel] [PATCH v3 2/7] libdtrace: share vmlinux BTF/CTF globally to support faster startup
Alan Maguire
alan.maguire at oracle.com
Thu Jul 23 13:22:10 UTC 2026
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 <alan.maguire at oracle.com>
>> ---
>> 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
>>
>>
>>
More information about the DTrace-devel
mailing list