I recently wanted to watch the thread count history of a running application as a graph in Instruments. I didn’t find a built-in instrument that showed me exactly what I needed, so I configured a custom instrument.
Custom instruments are based on dtrace probes. When I set up a custom instrument, I usually write a pure dtrace script first, independent of Instruments. It’s easier to tweak it until I get it exactly right, and it’s useful to have a command line variant anyway. When that works, I copy/paste the relevant parts into the instrument configuration sheet.
The main task was figuring out which providers and probes to use. A DTrace documentation search for various combinations containing “thread” didn’t turn up anything useful. I later realized and remembered that the Solaris/DTrace terminology for thread is light weight process, and indeed there are lwp-create and lwp-exit probes in the proc provider that fire at the appropriate times. What helped me find these probe names were the Darwin kernel sources. The locations that set up threads are instrumented accordingly (look for lwp__create and lwp__exit).
The curpsinfo->pr_nlwp value provides the number of threads. Putting everything together results in this script (which is on github):
BEGIN
{
globalIndex = 0;
}
proc:::lwp-start
/pid == $target/
{
this->mIndex = ++globalIndex;
printf("[%d] thread start, count = %d", this->mIndex, curpsinfo->pr_nlwp);
}
proc:::lwp-exit
/pid == $target/
{
this->mIndex = ++globalIndex;
printf("[%d] thread exit, count = %d", this->mIndex, curpsinfo->pr_nlwp);
}
Run it like this, replacing 1234 with your target process id:
sudo dtrace -s thread-count.d -p 1234
The output looks like this:
thread_info_internal:lwp-create 1287183987 [710] thread create, count = 34 thread_info_internal:lwp-create 1287183987 [713] thread create, count = 35 thread_terminate_self:lwp-exit 1287183987 [715] thread exit, count = 34 thread_info_internal:lwp-create 1287183989 [716] thread create, count = 34 thread_info_internal:lwp-create 1287183989 [717] thread create, count = 35 ...
The configuration in Instruments:

The options provided by the instrument inspector define what gets plotted:


And finally the result:

|


