[DTrace-devel] [PATCH] Action clear() should clear only one aggregation

Kris Van Hees kris.van.hees at oracle.com
Thu Aug 15 01:06:04 UTC 2024


On Wed, Aug 14, 2024 at 07:05:44PM -0400, Eugene Loh wrote:
> On 8/14/24 18:28, Kris Van Hees wrote:
> 
> > On Wed, Aug 14, 2024 at 05:50:27PM -0400, Eugene Loh wrote:
> > > On 8/14/24 11:57, Kris Van Hees wrote:
> > > 
> > > > On Tue, Aug 13, 2024 at 10:59:25PM -0400, eugene.loh at oracle.com wrote:
> > > > > From: Eugene Loh <eugene.loh at oracle.com>
> > > > > 
> > > > > FIXME:  Is libdtrace/libdtrace.ver correctly updated?
> > > Incidentally, what has to be done in this file?
> > > 
> > > > I think that keeping dtrace_aggregate_walk() as-is would be better, along with
> > > > adding a function dtrace_aggregate_clear_one(dtp, aid) that performs the
> > > > lookup from aid to dtrae_aggdata_t *agd, and then calls
> > > > dt__aggregate_clear_one(agd, dtp) to do the actual clearing.  There is no need
> > > > to go through a walker function when we already know we need to operate on
> > > > just one aggregation.
> > > I'm not convinced.
> > > 
> > > "Just one aggregation"?  Yes, just one aggid, but possibly many keys.  To
> > > narrow down to which agd we want, we need to know the key -- and clear()
> > > doesn't give us the key, plus there will generally be more than one key
> > > anyhow.
> > Ah true.  I blanked on the fact that clear(@a) clears that aggregation, and
> > any indexed aggregations with the same name (and thus same aid).
> > 
> > Anyway, given that dtrace_aggregate_walk() is an API function that is exported
> > by libdtrace, we should not change it.
> > 
> > So, I'd propose that instead of introducing a new function, we can make use
> > of the existing dtrace_aggregate_walk() by passing both dtp and the aid as an
> > arg struct.  E.g.
> > 
> > typedef struct dt_clear_arg {
> > 	dtrace_hdl_t	*dtp;
> > 	dtrace_aggid_t	aid;
> > } dt_clear_arg_t;
> 
> Hmm.  Then both dt_consume.c and dt_aggregate.c need to know about this new
> struct.  So, copy it to both files?  Introduce a new dt_aggregate.h?  Ick.

It would be appropriate to add it to dt_aggregate.h because it is a struct that
defines the callback argument.  There is enough precedent for that - in fact,
it is the way this is typically done.

> Maybe the thing to do is use dtrace_aggregate_walk() with a callback in
> dt_consume.c.  The callback can filter on the agg id and call
> dt_aggregate_clear_one() accordingly... I *think* that works.  Let me know
> if you're on board with this approach.

I think I'd rather see the dt_clear_arg_t thing.  I don't think a callback in
dt_consume.c would work without this struct argument because you still would
not be able to get both dtp and aid passed to that callback.

> > void
> > dtrace_aggregate_clear(dtrace_hdl_t *dtp)
> > {
> > 	dt_clear_arg_t	arg = { dtp, aid };
> > 
> >          dtrace_aggregate_walk(dtp, dt_aggregate_clear_one, &arg);
> > }
> > 
> > nd then dt_aggregate_clear_one() can check the aid and return if the aid
> > is not IDNOE and does not match the one for the aggregation it is called for.
> > That means you also need to change dt_aggregate_snap_one() but there you can
> > also define that arg and set aid as IDNONE in that because we know that if we
> > call dt_aggregate_clear_one() from here weknow it is for an aggregation that
> > needs to be cleared.
> > 
> > > Now, one can argue that in the current implementation and its current hash
> > > function, the aggid tells us at least which hash bucket to search.  So we
> > > could write a special, reduced loop.  Maybe so, but that would be wed to
> > > this particular choice of hash function, and I'd argue the current choice is
> > > a bad one.  E.g., consider:
> > > 
> > >          tick-10 { @pc[uregs[R_PC]] = count() }
> > >          syscall::write:entry { @writeentry = count() }
> > > 
> > > Lots of agd's will be sharing one bucket and another agd is sitting all by
> > > itself.  We ought to change the hash function, and then we'd have to undo
> > > the "search just one bucket" optimization.
> > > 
> > > PS  Here is an oddity:
> > > 
> > >      # /usr/sbin/dtrace -n 'BEGIN { @a[1] = count(); @a[2] = count();
> > > clear(@a[1]); exit(0); }'
> > >      dtrace: description 'BEGIN ' matched 1 probe
> > >       CPU     ID                    FUNCTION:NAME
> > >        34      1                           :BEGIN
> > > 
> > >              1                0
> > >              2                0
> > > 
> > > You *can* specify the key in the clear()!  But dtrace ignores the key.
> > > Silently.  Same behavior in Solaris.



More information about the DTrace-devel mailing list