How To Use DTrace On Mac OS X

There are many performance analysis and troubleshooting tools for software engineers nowadays. The most popular among them are debuggers and profilers, which hook up to your program and show what’s going on or how much resources are occupied by who. These tools usually work in user space and don’t tell you much about how your program interacts with OS kernel. So if you need an ultimate drill down tool, DTrace could be the one.

Dtrace is included by default with Solaris, Mac OS X and FreeBSD. There is an equivalent for Linux, Strace, but it is not as great for troubleshooting production environments.

El Capitan by default enables System Integrity Protection, which significantly limits DTrace capability on your Mac. Read more on this and how to disable SIP here.

How DTrace works

DTrace operates by activating probes, which fire when your code goes through them. You use D language to specify which probes to activate and which actions to execute when a probe fires.

DTrace instruments each probe dynamically on the live, running operating system. It activates probes only temporarily and deactivates them when your DTrace session is over (you press Ctrl-C).

DTrace instrumentation is designed to be as efficient as possible, and enables you to use it in production to solve real problems in real time.

D language

In nutshell, D language lets you specify which actions to run if a probe you are interested in fires. The formal structure of D language instruction is:

<probe description>
/<condition>/
{
    <action1>;[<action2>; ...]
}

It’s easier to understand the structure if we start with an example. The following D program will show all read system calls made in iTerm.

syscall::read:entry
/execname == "iTerm"/
{
    printf ("%s called read, asking for %d bytes\n", execname, arg2);
}

As you can see, <probe description> is a complex structure on its own. It consists of four parts:

<provider>:<module>:<function>:<name>

<provider> gives access to classes of functions. A common provider is syscall, which lets you trace Unix system calls.

<module> depends on the provider and allows you to limit scope to a particular shared library in the module. Some providers don’t have modules.

function specifies the function you are interested in.

name depends on the provider. Most providers have entry and return. entry will execute D actions before the function starts, and return will execute after the function exits.

<condition> is optional. If it’s present, actions will be executed only when it evaluates to true.

<actions> are often printf commands, although other command are available.

If you need more details, have a look here.

In summary

DTrace is a great tool for low level analysis of your application. It lets you do fine grained analysis of applications running in production and drill down to kernel without affecting production performance.