Objective-C: Using Instruments to trace messages-to-nil

In Action_tn.png

In Leopard, Apple added a new tool to the developer tool suite called Instruments. It is a timeline based debugging and performance analysis tool. With a full suite of tools to analyze all kinds of dimensions of performance, correlating all data onto a timeline that can be inspected and navigated at will. And it remembers prior runs so you can compare results before and after changes.

And it fully consumes dtrace.

Clicking through the screenshot at right will show a run of Instruments with a single analysis instrument active.

I created a custom instrument that encapsulates the dtrace script I discussed in Objective-C: Using dtrace to trace messages-to-nil.

I ran the resulting instrument against TextEdit.

What can’t be conveyed by that screenshot is exactly how “live” the data can be examined. You can click and drag on the timeline to select a subset of the run, details of the selected instrument are shown in the table in bottom right, and any given row can be selected to show the backtrace active at the time the sample was taken.

I didn’t want to clutter up the screenshot with lots of data and, thus, didn’t demonstrate the awesomeness that is being able to relate data across multiple instruments, correlated by time.

That’ll be in the next Mac OS X / Software related post.

Click on through for an explanation with screenshots as to exactly how to convert the dtrace script to an instrument.

objc_msgSend Probe_tn.png

First, I set up a custom instrument to contain the script. Under the Instrument menu, select “Build new Instrument” (cmd-b).

You’ll get a sheet that looks a bit like the sheet at left, only without everything filled in.

As pictured, the sheet is filled in with exactly the same stuff as the aforementioned script.

The custom instrument panel offers options for recording data and, thus, the printf()/copyinstr() line of the original script is not required.

Likewise, the custom instrument has an option to capture any of a number of different kinds of stacks. I configured it to capture the stack trace within the user process (keep in mind that dtrace scripts run in the kernel and, thus, capturing kernel stack traces is easily done).

Better yet, when you click the OK button, the custom instrument is saved into Instrument’s library of instruments and can be easily reused in any Instruments document.

Executable Configuration_tn.png

The final step is to select an executable to analyze. Normally, you could start sampling an already running application. In this case, an environment variable — DYLD_SHARED_REGION — must be set prior to launching the process to be analyzed.

Thus, the screenshot at left shows the “Launch Executable…” sheet configured to launch TextEdit with the proper value for the environment variable.

Now, it is just a matter of hitting the red record button and gathering some data!



5 Responses to “Objective-C: Using Instruments to trace messages-to-nil”

  1. Adrian Milliner says:

    Nice series – I hope it gets more people interested in dtrace/Instruments.

  2. bbum says:

    I hope so, as well. Dtrace is awesomely powerful stuff, but the initial learning curve can be a bit daunting.

  3. Michael Tsai - Blog - Logging Messages to Nil says:

    […] Update 2: How to do it with Instruments. […]

  4. The Omni Mouth » More objc method tracing says:

    […] Objective-C: Using Instruments to trace messages-to-nil […]

  5. Tom Bunch says:

    I adapted your instrument to collect calls to objc_msgSend_stret(, nil, …), if arg1 == 0, recording arg2 (Selector). I immediately verify one known bug in my code (using [nil frame]), found a new one, and discovered that when opening a document view in OmniPlan system frameworks call [nil bounds] 50 times, most of them in -[NSView _updateLayerGeometryFromView]. Very useful!

Leave a Reply

Line and paragraph breaks automatic.
XHTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>