[DTrace-devel] [PATCH v2 09/11] htab reduction: providers
Eugene Loh
eugene.loh at oracle.com
Fri Oct 22 14:52:24 PDT 2021
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
On 10/20/21 2:54 PM, Nick Alcock wrote:
> The list of providers is a hand-rolled fixed-size htab which is grossly
> oversized except when USDT or the pid provider is in use, when it can
> suddenly become terribly undersized: replace it with a dt_htab.
Personal taste: I'd prefer a full stop in place of that colon.
Also, the "list of providers" was separate from the hash table.
How about:
Providers were stored in fixed-size hash tables and companion
lists. The fixed-size tables generally were grossly oversized;
with USDT or pid, they were terribly undersized.
Eliminate the lists and replace the hash tables with dt_htab.
But, your call.
> We can move to using destructors (allowing deletion of htab elements
> without needing a specialized _destroy function, and straightforward
> freeing of the dt_provs htab on dtrace_close), but this is a little
> troublesome because the dt_provlist is separate from dt_provs,
> inaccessible from dt_provs element destructors (which do not have access
> to a dtp), yet its members are added/removed from the dtp as we go.
>
> We can fix this by dropping the dt_provlist and replacing it with
> dt_htab_next-based iteration over dt_provs. The iteration order is
> different, but that's all that changes.
>
> (This is... debatable, and I can see why people might prefer to keep the
> old design and just keep a dtp backpointer in every provider element.
> I'm happy with that approach too.)
I'm having trouble reading those three paragraphs. What I do know is
that some stuff that was allocated with dt_zalloc(dtp, ...) and freed
with dt_free(dtp, ...) is now sometimes (but not always) freed with
free(...). I guess that's okay -- dt_free() is really just a free() --
but that seems like a sufficiently big "architectural change" that... I
dunno. Anyhow, I can see why you flag the issue, even if I don't
understand this explanation of it.
> diff --git a/libdtrace/dt_dof.c b/libdtrace/dt_dof.c
> @@ -560,6 +560,7 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
> uint_t maxfmt = 0;
> #endif
>
> + dt_htab_next_t *it = NULL;
> dt_provider_t *pvp;
> dt_xlator_t *dxp;
> dof_actdesc_t *dofa;
How about moving that declaration down into the clause where it is used?
> @@ -746,8 +747,7 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
> * to the providers and the probes and arguments that they define.
> */
> if (flags & DTRACE_D_PROBES) {
> - for (pvp = dt_list_next(&dtp->dt_provlist);
> - pvp != NULL; pvp = dt_list_next(pvp))
> + while ((pvp = dt_htab_next(dtp->dt_provs, &it)) != NULL)
> dof_add_provider(ddo, pvp);
> }
Into this clause.
> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> @@ -324,9 +324,7 @@ struct dtrace_hdl {
>
> struct dt_probe *dt_error; /* ERROR probe */
>
> - dt_list_t dt_provlist; /* linked list of dt_provider_t's */
> - struct dt_provider **dt_provs; /* hash table of dt_provider_t's */
> - uint_t dt_provbuckets; /* number of provider hash buckets */
> + dt_htab_t *dt_provs; /* hash table of dt_provider_t's */
> uint_t dt_nprovs; /* number of providers in hash and list */
> const struct dt_provider *dt_prov_pid; /* PID provider */
> dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
The comment "and list" for dt_nprovs no longer makes sense since there
is no more list. Actually, dt_nprovs is not even used for anything.
IMHO, it can be removed entirely.
> diff --git a/libdtrace/dt_pcb.c b/libdtrace/dt_pcb.c
> @@ -127,8 +128,7 @@ dt_pcb_pop(dtrace_hdl_t *dtp, int err)
> - for (pvp = dt_list_next(&dtp->dt_provlist); pvp; pvp = nvp) {
> - nvp = dt_list_next(pvp);
> + while ((pvp = dt_htab_next(dtp->dt_provs, &it)) != NULL) {
> if (pvp->pv_gen == dtp->dt_gen) {
> dtrace_probedesc_t pdp;
>
> @@ -141,7 +141,7 @@ dt_pcb_pop(dtrace_hdl_t *dtp, int err)
> dt_probe_iter(dtp, &pdp, dt_pcb_destroy_probe,
> NULL, NULL);
>
> - dt_provider_destroy(dtp, pvp);
> + dt_htab_next_delete(it);
> }
> }
This code is okay, but it's an interesting example of some things I
mentioned. E.g., the old code would destroy pvp, which was okay since
it already picked up nvp. Using a similar approach, one would not need
a special dt_htab_next_delete() function. Alternatively, have the
iterator stop at the entry *after* the one that is returned, and then
you could delete entries as you iterated through the list.
More information about the DTrace-devel
mailing list