[DTrace-devel] [PATCH] examples: add script fcalls.d

Kris Van Hees kris.van.hees at oracle.com
Wed Aug 6 18:50:42 UTC 2025


On Mon, Aug 04, 2025 at 08:06:59PM -0400, Eugene Loh wrote:
> Reviewed-by: Eugene Loh <eugene.loh at oracle.com>

I am confused... is this a R-b that means that the patch can go in as-is, or
are you expecting changes?  I also see discussion about a README.  Is that a
prerequisite or companion patch that is expected to go in with this one, or
is this one separete and could potentially go in on its own before a README?

> I wouldn't mind a blank line separating each clause from the comment block
> that follows it.
> 
> Incidentally, when git applies a patch with "git am", it squeaks when there
> is trailing white space.  In this case, "both" (at the end of a line) was
> followed by a space.  (That trailing space was removed for this patch, but
> might still be in the original.)
> 
> Depending on where we want to go with this, it'd be nice to have tests for
> examples, so that if an example is going to break that we'll know about it. 
> There is currently a test/demo directory with a similar purpose but
> antiquated tests.  Maybe there could be a test/examples directory.  The
> trigger code could possibly be something we already have.  E.g., in
> test/triggers/* -- something that terminates by itself (or not) and has
> nontrivial call stack (for this example) or even multithreaded!  And
> predictable (checkable) behavior.  Possibilities include:
>     test/triggers/futex
>     test/triggers/libproc-dlmadopen (multithreaded)
>     test/triggers/ustack-tst-basic
> but one could argue that's beyond the scope of this patch.
> 
> On 8/4/25 19:42, eugene.loh at oracle.com wrote:
> > From: Ruud van der Pas <ruud.vanderpas at oracle.com>
> > 
> > This is a script to list and count function calls.
> > 
> > dtrace/ChangeLog
> > 2025-08-01  Ruud van der Pas  <ruud.vanderpas at oracle.com>
> > 
> > 	* examples/fcalls.d: List and count function calls.
> > 
> > Signed-off-by: Ruud van der Pas <ruud.vanderpas at oracle.com>
> > ---
> >   examples/fcalls.d | 88 +++++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 88 insertions(+)
> >   create mode 100755 examples/fcalls.d
> > 
> > diff --git a/examples/fcalls.d b/examples/fcalls.d
> > new file mode 100755
> > index 000000000..8116ecc6f
> > --- /dev/null
> > +++ b/examples/fcalls.d
> > @@ -0,0 +1,88 @@
> > +#!/usr/sbin/dtrace -s
> > +
> > +/*
> > + *  NAME
> > + *    fcalls.d - list the functions executed by an application
> > + *
> > + *  SYNOPSIS
> > + *    sudo ./fcalls.d -c "<name-of-application> [app options]"
> > + *
> > + *  DESCRIPTION
> > + *    This program lists the functions executed by the target
> > + *    application.  In addition to this, the number of calls to
> > + *    each function is printed.  This information is given on a
> > + *    per-thread basis, as well as aggregated over all threads.
> > + *
> > + *  NOTES
> > + *    - Since a.out is used in the probe definitions, library calls
> > + *    are excluded.  If a library like libc should be included,
> > + *    duplicate the probe definitions and in the copied lines
> > + *    replace a.out by libc.so.
> > + *    For example:
> > + *    pid$target:a.out::entry,pid$target:libc.so::entry
> > + *      { ... }
> > + *    - It is assumed that a function called main is executed.
> > + *    If this is not the case, this is not a critical error.
> > + *    The first probe is used to capture the name of the executable,
> > + *    but this is not critical.  The probe and printf statement
> > + *    can safely be removed, or replaced by a suitable alternative.
> > + */
> > +
> > +/*
> > + *  Suppress the default output from the dtrace command and
> > + *  have printa() print the data sorted by the first field.
> > + */
> > +#pragma D option quiet
> > +#pragma D option aggsortkey=1
> > +#pragma D option aggsortkeypos=0
> > +
> > +/*
> > + *  Store the name of the target application.  The probe
> > + *  is restricted to main only, because the exec name needs
> > + *  to be captured only once.
> > + */
> > +pid$target:a.out:main:entry
> > +{
> > +  executable_name = execname;
> > +}
> > +/*
> > + *  Use 4 aggregations to store the total number of function
> > + *  calls, the counts per function and per thread, both
> > + *  seperately and differentiated by thread and function.
> > + */
> > +pid$target:a.out::entry
> > +{
> > +  @total_call_counts                          = count();
> > +  @call_counts_per_function[probefunc]        = count();
> > +  @call_counts_per_thr[tid]                   = count();
> > +  @counts_per_thr_and_function[tid,probefunc] = count();
> > +}
> > +/*
> > + *  Print the results.  Use format strings to create a
> > + *  table lay-out.
> > + */
> > +END {
> > +  printf("===========================================\n");
> > +  printf("      Function Call Count Statistics\n");
> > +  printf("===========================================\n");
> > +  printf("Name of the executable: %s\n" ,executable_name);
> > +  printa("Total function calls  : %@d\n", at total_call_counts);
> > +
> > +  printf("\n===========================================\n");
> > +  printf("      Aggregated Function Call Counts\n");
> > +  printf("===========================================\n");
> > +  printf("%-25s %12s\n\n","Function name","Count");
> > +  printa("%-25s %@12d\n", at call_counts_per_function);
> > +
> > +  printf("\n===========================================\n");
> > +  printf("      Function Call Counts Per Thread\n");
> > +  printf("===========================================\n");
> > +  printf("%-7s %12s\n\n", "TID","Count");
> > +  printa("%-7d %@12d\n", at call_counts_per_thr);
> > +
> > +  printf("\n===========================================\n");
> > +  printf("      Thread Level Function Call Counts\n");
> > +  printf("===========================================\n");
> > +  printf("%-7s  %-25s %8s\n\n","TID","Function name","Count");
> > +  printa("%-7d  %-25s %@8d\n", at counts_per_thr_and_function);
> > +}



More information about the DTrace-devel mailing list