[DTrace-devel] [PATCH v2 09/11] htab reduction: providers
    Nick Alcock 
    nick.alcock at oracle.com
       
    Mon Nov  1 05:27:00 PDT 2021
    
    
  
On 22 Oct 2021, Eugene Loh said:
> 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.
Agreed. I seem to have colons on the brain right now.
> 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.
Yours is better.
>> 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 
Rephrased a bit:
    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, and since
    dt_provs element destructors don't have access to a dtp, the destructors
    also can't get at the dt_provlist to unchain dt_provs elements that are
    being deleted.
> 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.
We have no choice: the place that does the free has no way to get access
to a dtp unless we explicitly start dragging around dtp back-pointers
and wasting space just so we can pass it to a function that then does
nothing with it. Since the wrappers are useless and used only
inconsistently I wouldn't call using them less an architectural change :)
I hate the dt_ allocate/free wrappers with a passion. I'd really like to
coccinelle up the source tree and just delete the lot, or at least
delete their unused-but-if-you-pass-NULL-it-kills-you dtp argument.
>> 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?
Good idea.
>> 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.
Yes indeed! It's gone.
>> @@ -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.
With the htab iterator now keeping track of the element it'll return on
the next call, this is now:
		dt_htab_delete(dtp->dt_provs, pvp);
... which is probably at least a bit clearer.
-- 
NULL && (void)
    
    
More information about the DTrace-devel
mailing list