Here is an example of how incredibly powerful DTrace can be. I had to solve a problem where a nice high-level overview of the code flow in a single threaded userland application would save me some pain the backside. Lo and Behold, Dtrace – The Universal Hammer for every nail.
Here is a simple visual call graph generator using 5 lines of DTrace combined with the outstanding Graphviz graphics library.
$ cat callgraph.d
pid$target:a.out::entry
{
@call_stats[ufunc(ucaller), strjoin(strjoin(probemod,"`"), probefunc)] = count();
}
END
{
printf("digraph foo {\n");
printa(" \"%A\" -> \"%s\" [weight=%@d];\n", @call_stats);
printf("}\n");
}
Run the script using the following command line and feed the dtrace output to one of the graphviz graph generators such as dot or neato or circo.
$ dtrace -q -o graph.in -s ./callgraph.d -c /usr/bin/ls
$ dot -T jpg -o callgraph.jpg graph.in
Voila ! Here is the output:
Nice ! You know – Picture, 1024 words and all that stuff.
P.S: Only for the insanely curious
_start: This is the *real* entry point of any dynamically linked executable. This is the function that calls into main and does the atexit cleanup after main returns.
__fsr : This is the trap handling code for floating point. No idea why this is a named global. _start calls __fsr as function which is why the graph looks the way it does.
qsort: This is the solaris libc implementation of Quick Sort. The reason you see this as a disconnected subgraph is because the D script is tracing only functions from a.out (ls in this case). libc.so.1 functions are not traced. But they do get recorded because I look at the first level caller in the stack. And because qsort uses a callback to do the item comparision during sort, you get a graph edge that says
libc.so.1`qsort -> ls`compare
And you don’t record the edge that would have said
ls`pdirectory -> libc.so.1`qsort
So the link between and ls and libc.so.1 is cut-off. Of course, if you enable the probe for all libc.so.1 functions or all library functions and so on, you would get the “complete” picture. But that happens to be slightly overwhelming. Unsuitable for muggles who might chance to read this
Filed under: Open Source, Operating Systems, Programming, Solaris

This would make a great demo for developers.
Ananth, can the same script be used for analyzing byte code (a.class as target)? I would be interested to see how it generates a graph where a java class is making a call to a native class written in C++. If you have a sample, please post.
@ Sundar,
The same could be done for Java or C++ or Python or Ruby or Javascript or any of the languages DTrace supports.
In case of java, you would use the hotspot$pid:::method-entry and hotspot$pid:::method-return probes to track function calls.
Ananth, this is impressive. I tried it on one of the PL/SQL parser I was writing on Ruby (just for getting used to Ruby). Very helpful. Only problem is that it is damn addictive, just like Ruby itself.
Sweet
[...] может быть использование graphviz (материал взят из блога Thermal Noise). Небольшой D-программой можно генерировать [...]
This kinda’ rocks
I looked for dtrace, but all I find is DTraceToolkit, and I don’t seem to find the actual dtrace executable inside it. Can you please point me to the source/binaries?
@ ashish
DTrace is not a standalone binary – Its a framework. The pieces necessary for dtrace all ship with opensolaris by default. If you have opensolaris, you already have DTrace.
The sources are in several places inside the opensolaris tree. A good place to start might be:
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/dtrace/
and
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/dtrace/