[DTrace-devel] [PATCH] test: clean up orphaned tracing events between tests

Nick Alcock nick.alcock at oracle.com
Wed Jun 7 10:09:45 UTC 2023


On 7 Jun 2023, Kris Van Hees via DTrace-devel outgrape:

> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>

Significant changes suggested below: equally significant reduction in
runtime expected :)

> ---
>  runtest.sh                 |   2 +
>  test/utils/Build           |   2 +-
>  test/utils/clean_probes.sh | 102 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 105 insertions(+), 1 deletion(-)
>  create mode 100755 test/utils/clean_probes.sh
>
> diff --git a/runtest.sh b/runtest.sh
> index a39a1c91..17589d85 100755
> --- a/runtest.sh
> +++ b/runtest.sh
> @@ -1500,6 +1500,8 @@ for dt in $dtrace; do
>              cp -f $tmpdir/test.out $base.r
>          fi
>  
> +	test/utils/clean_probes.sh >> $LOGFILE
> +

Total pedantry: runtest.sh uses spaces, not tabs :)

> diff --git a/test/utils/clean_probes.sh b/test/utils/clean_probes.sh
> new file mode 100755
> index 00000000..5e931232
> --- /dev/null
> +++ b/test/utils/clean_probes.sh
> @@ -0,0 +1,102 @@
> +#!/usr/bin/bash
> +
> +TRACEFS=/sys/kernel/debug/tracing
> +EVENTS=${TRACEFS}/available_events
> +KPROBES=${TRACEFS}/kprobe_events
> +UPROBES=${TRACEFS}/uprobe_events
> +
> +# Check permissions
> +if [ ! -r ${EVENTS} ]; then

Throughout: [ is (much) slower than [[ in bash and has awful semantics.
[[ ... ]] is almost always preferable.

> +# Scan the list of events for any orphaned DTrace probes
> +(
> +	ps -e

Rather than using a ps -e and then parsing the heck out of it, why not
do something like

(ps -C dtrace -o pid=
 echo ===
 cat ${EVENTS})

and then accumulate everything you see into pids, then match on /---/
and treat everything later as an event? Actually we don't even need (),
we're not changing anything that uses a subprocess: {} is enough.

This is really quite a lot faster, too -- ps has to do less work, and
it doesn't collect things it doesn't have to:

oranix at loom 3010$ strace ps -e 2>&1 >/dev/null | wc -l
19372
oranix at loom 3011$ strace ps -e -o pid 2>&1 >/dev/null | wc -l
11576
oranix at loom 3012$ ps -C dtrace -o pid 2>&1 >/dev/null | wc -l
9830

So... something like:

{ ps -C dtrace -o pid=; echo ===; cat ${EVENTS}; } |
    awk -v tracefs=${TRACEFS} \
        'BEGIN { events = 0; }
        /^===$/ { events = 1; next; }
        !events { pids = pids "|" int($1); next; }

... and then something else, because I'll admit I have no idea what's
going on in most of the rest of it, !processing and below: it's
presumably uprobe_events stuff which is probably pretty much ok as is,
or at least probably not too expensive and too complex like the
ps-parsing stuff. (I'm not even sure why the variable 'processing'
exists.)

(btw, did you know that the format of ps sans -o depends on an
environment variable, PS_FORMAT? Always, always use -o when using ps in
scripts.)

(original below for comparison)

> +	cat ${EVENTS}
> +) | \
> +	awk -v tracefs=${TRACEFS} \
> +	    'function getTimestamp(dt) {
> +#		 cmd = "date --rfc-3339=ns";
> +		 cmd = "date +\"%s.%N\"";
> +		 cmd | getline dt;
> +		 close(cmd);
> +		 return dt;
> +	     }
> +
> +	     function timeDiff(t0, t1, s0, n0, s1, n1) {
> +		 tmp = $0;
> +
> +		 $0 = t0;
> +		 sub(/\./, " ");
> +		 s0 = int($1);
> +		 n0 = int($2);
> +		 $0 = t1;
> +		 sub(/\./, " ");
> +		 s1 = int($1);
> +		 n1 = int($2);
> +
> +		 if (n1 < n0) {
> +		     s1--;
> +		     n1 += 1000000000;
> +		 }
> +
> +		 $0 = tmp;
> +
> +		 return sprintf("%d.%09d", s1 - s0, n1 - n0);
> +	     }
> +
> +	     BEGIN { start = getTimestamp(); }
> +
> +	     NF > 1 {
> +		 if (/dtrace/)
> +		     pids = pids "|" int($1);
> +		 next;
> +	     }
> +
> +	     !processing {
> +		 re = "^dt_" substr(pids, 2) "_";
> +		 processing = 1;
> +	     }
> +
> +	     $1 !~ /^dt_[0-9]/ { next; }
> +	     $1 ~ re { next; }
> +	     { sub(/:/, "/"); }
> +
> +	     {
> +		 if (/_fbt_/)
> +		     kpv[kpc++] = $0;
> +		 else
> +		     upv[upc++] = $0;
> +	     }
> +
> +	     END {
> +		 fn = tracefs"/kprobe_events";
> +		 for (i = 0; i < kpc; i++) {
> +		     print "-:"kpv[i] >> fn;
> +		     if (i % 20 == 19)
> +			 close(fn);
> +		 }
> +		 close(fn);
> +
> +		 fn = tracefs"/uprobe_events";
> +		 for (i = 0; i < upc; i++) {
> +		     print "-:"upv[i] >> fn;
> +		     if (i % 20 == 19)
> +			 close(fn);
> +		 }
> +		 close(fn);
> +
> +		 diff = timeDiff(start, getTimestamp());
> +		 txt = sprintf(" (%d kprobes, %d uprobes)", kpc, upc);
> +		 print "Cleaning took " diff txt;
> +	     }'
> +
> +exit 0



More information about the DTrace-devel mailing list