Thermal Noise

Icon

The Adventures Of A Unix Programmer

Visual Call Graph using DTrace

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:

DTrace Callgraph of /usr/bin/ls

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

9 Responses

  1. Joe says:

    This would make a great demo for developers.

  2. Sundar says:

    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.

  3. Ananth says:

    @ 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.

  4. Sundar says:

    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. ;-)

  5. [...] может быть использование graphviz (материал взят из блога Thermal Noise). Небольшой D-программой можно генерировать [...]

  6. praetor says:

    This kinda’ rocks ;-)

  7. 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?

  8. Ananth says:

    @ 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/

Leave a Reply

SocialVibe


Twitter

  • After several years of disgust with Python's subprocess and its numerous bugs, I finally wrote my own extension module in C. Unix FTW ! 1 day ago
  • Celebrated 1st year in Google by keeping awake all night to solve a nasty SWIG preprocessor issue and a readline escape sequence parsing bug 1 day ago
  • http://bit.ly/lW8SQ - Smart Energy Meters that can Tweet. Wow ! Gazprom may not be the only beneficiary of EU energy deregulation after all. 3 days ago
  • The US doesn't want foreign workers but sends medical tourists to the third world (http://bit.ly/O9eoo). Medicare FAIL. Free market FAIL. 6 days ago
  • The algebra student fails the grammar test: "i is an imaginary number" 1 week ago

Archives