Tools • 56:55
Instruments and DTrace are powerful software analysis tools introduced in Mac OS X Leopard. Explore how you can use these tools to solve specific application and system performance issues. Discover advanced profiling and inspection techniques including adding static DTrace probes in your code, building new instruments to collect data from your custom probes, and using Instruments' data analysis features to study results.
Speakers: Dave Payne, Chad Woolf
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning everyone. Glad to see we've packed the house at 9 a.m. on Friday morning after the party. I hope you all had a great time. All right. My name is Dave Payne. I'm the manager of the Analysis Tools team, so that's debugging and performance analysis tools. In the session this morning, we're going to look at some new ways to try to understand the behavior of your applications. We'll take a look at reviewing Instruments and DTrace, look at how to trace functions and methods in your application, how to build custom Instruments with DTrace, and how to build static probes with DTrace and use those static probes.
So this session is relevant for pretty much everyone at the conference. Mac developers where we introduced Instruments and DTrace in Leopard. For iPhone developers, you can use Instruments with either the iPhone simulator or on the iPhone itself. DTrace is available for your iPhone applications when you're running in the iPhone simulator because they're really effectively a Mac application at that point. And Information Technologies people can use Instruments to analyze your entire system and see what's going on, for example, on a server.
So as a recap, Instruments is a great way to visualize the behavior and performance of your application or your entire system. It allows you to collect multiple types of event data simultaneously in different tracks and then filter that data down and sort it in different ways to really do data mining and hone in to find the problems you're having. This lets you turn your classical edit, build, debug cycle into edit, build, debug, analyze, performance tune, so streamline that entire cycle.
Instruments comes with quite a variety of built-in instrumentation that's very powerful. Much of this is based on the Leopard frameworks like the ObjectAlloc and Leaks instruments, CPU Sampler. And then we have a number of built-in instruments that are based on DTrace.
[Transcript missing]
So let me do a virtual demo and show you how that works in action here. So I go into a terminal window and I can use the sudo dtrace-l command to list all the probes in the system. We had about 25,000 of them on Leopard. When we tried it recently on Snow Leopard, we had over 60,000.
And a lot of them are duplicated probes from static probes in the framework that appear in multiple different processes. But you can see here that, so this is a listing of all the built-in probes that are available. They're a bunch of different providers in a variety of different modules, different functions, and different names. So I've written a simple little script here called syscalldemo.d.
So the probe descriptor here is saying I want to use the syscall provider to watch system calls, and specifically the open system call. I want to trap on the entry of open system call. And I'm using a predicate on this to say I'm really only interested in it if the executable name is calculator when this probe fires.
Then I have a couple of action statements. One to do a printf line to say what app opened what file. So in this case I use, again, exec name as a built-in variable. It's always going to be calculator in this example because of the predicate. Then I can use arg0, which is the file name argument to open. Now because the probe is firing in kernel space, it doesn't directly have access to the file name there. All it gets is the pointer.
But it can use a DTrace function called copy in string to reach out into user space and copy that C string into the kernel for recording with this event. I'm also using the uStack50 call to say I want to see the first 50 frames of the stack when this event fires. So let me go ahead and execute this script.
So I do a sudo DTrace-S to say this particular script. We see that it matches one probe. I flip over to Calculator, change the window size a couple of times, and we've seen that it fired a couple of events. Flip back over to Terminal, scroll up to the top, and we can see that we get the printf line at the top. Calculator opened a global preference file, and then down below /dev/autoFS/nowait, and we see the backtrace of where these events occurred. So you can do this on the command line. You can write any scripts that you need to write there.
So we've referred to DTrace providers. I like to think of the providers as being in three categories: system-wide providers, per-process providers, and user-land static probes.
[Transcript missing]
So let's take a look at how you'd use this to build custom instruments. So first off, why would you want to do that?
Well, you know your own code. We can't imagine all the problems that you're going to want to solve because they're particular to your domain. And you can also tailor instruments for different types of tasks, such as bug hunting, assertion checking, regression testing. You could use the UI recorder instruments with custom instruments that you've written to execute your application time and time again.
Say each time you modify your code, you could rerun a UI recording and make sure that you get similar results from your custom instruments to make sure that you haven't broken your program. Or you could do network administration tools in your environment. Again, very similar to DTrace itself. You can pose and answer arbitrary questions in this way.
So for example, assertion checking. A lot of times you'll use something like NSAssert to check input parameters to functions. Most people compile these out of their production release. But with DTrace, you could put probes on functions that you could turn on at runtime, gather the input, and check those sort of externally from your program. You can also use the DTrace actions and its other mechanisms to maintain state of what's going on. So you can do broader levels of validity checking. You know, if function A got these arguments, then function B should have this.
To build a new DTrace instrument, you use the Build New Instrument or Trace Symbol menu items from the Instrument menu. You can also edit an existing DTrace instrument by using the Edit Instrument menu item. Or if you have an instrument in a trace document, you can just double-click on it to bring up the instrument builder.
So for example, the easiest way to leverage the flexibility of DTrace is Trace Symbol. You just enter in a function name that you want to trace, such as fprintf or nslog, or an Objective-C method name. In this case, Instrument Builder knows about Objective-C and it converts the colons in your method names to asterisks for you. When you're using the Trace Symbol, you can also use wildcards in class names.
So you could say, for example, I want to trace all my set methods, which would include those for access or set methods on properties that get generated by the compiler for you. Or you could trace a method on multiple different classes. When you bring up the Instrument Builder, it comes down as a sheet on your trace document.
There's multiple different categories, areas in the Instrument Builder sheet. The top area is a way to communicate to instruments how this instrument should appear in the library. So it lets you specify a human-readable name, a category in the instrument's library to put it in, and a human-readable description, which gets looked at when you type into the filter field of the library.
There's a data field in case you need to declare any variables for this, and a lot of times you won't need to because DTrace doesn't require it. If you need to initialize any variable values, you can do it in the begin field. And then the heart of the Instrument Builder is the probe clause. So there's three different sections of this. One is the probe condition where you specify the probe itself and any predicates.
And then the probe condition where you specify the probe itself and any predicates. So in this case, we're using the profile provider to fire at one-second intervals. And you can see there's a pop-up for what type, which is the provider. Then there's the action portion of your script. And finally, something custom for Instruments is what data do we want to record to have it appear in the detail view for this instrument or be shown in the track view.
And finally, there's an end section, which a lot of times you won't need to use with instruments that you build here. Once you've created your new instrument, you can just hit the Save button and it gets saved. If you are editing an existing instrument, then we say, well, okay, we want to be safe here by default and not trash your old instrument or the data that is recorded with it. So the default is to save a copy. But you'll note that we have a checkbox on the left, and this is new to Xcode 3.1, that says preserve previous instruments and recorded data.
So when we're doing a save copy, that checkbox is checked. But if you uncheck that, that lets you experiment with one instrument and do an iterative, edit the instrument, save it, try it, edit again, save it, try it, until you get an instrument that you're happy with. So rather than getting six instruments created out of that, you can just edit one. So that's really convenient. I like it too. So now we'd like to take a case study of exploring our poor little baffle application. So I'd like to call up my colleague, Chad Woolf.
Thank you, Dave. Yeah, we're going to take a look at the Baffle Cocoa application again. That's the Mr. Bill application of WWDC 2008. So, Dave has shown you how we can create custom instruments using DTrace. So let's look at an example. So our Baffle Koku application is up there. And on a Friday we get an email saying, OK, we've added a new feature.
This new feature allows you to flip back and forth through the list of words that you've gotten in various games. And so please update your sources. And so I did. Merged it with my code, took a look at it. So I started a new game, finished it, got three words, and I go to the back button.
But when I click it, I notice that the word list is kind of bizarre looking. That's not really what I remembered. So what I'm looking at here is it looks like a list of the same number of words. The score is correct. Then the number of letters in each word seem to be matching. But the letters themselves are a little scrambled.
So let's take a look at what we know about the BaffleCoco app. It has a word list on the right and the pieces on the board on the left. Now, the word list on the right, each word is represented by a BG Baffle word object. And the pieces on the board are represented by the BG Baffle piece object.
Now what's interesting is the BG Baffle word actually refers or is composed of pieces so that when you execute its get me your string representation there, it iterates through that array of pieces and constructs you string dynamically. So that's potentially pretty suspect. But without jumping to any conclusions, we definitely want to look at both possibilities and that is maybe the word is being changed. So I copy the word into the history list and then maybe something's inserting pieces or removing pieces. Those are the two methods that we have for changing a word.
Or the other possibility, which seems a little bit more likely based on what we've seen, is that the pieces themselves are changing. And this can happen potentially if we didn't do a deep copy. We copied the words, but we didn't also copy the pieces, and maybe they're being referred to the same, or maybe the words are referring to the same pieces that are still on the board. So I'm going to hop into Instruments over here with our running baffle application.
Now without, without, now see I'll show you how it's exhibiting the problem here. Okay, that's obviously trash but the score is valid. And without taking it down, I'm going to call up Instruments. Sometimes when you're debugging something, you don't want to take it down, so attaching to it through Instruments is a great idea. Starting from a blank template, I'm going to go to Instrument, and I'm going to say Trace Symbol.
The first thing we wanted to look at was our Word class, and we wanted to see if our Word class was being modified before or after it was being copied into the old list. So I type in bgbaffleword with an asterisk, so I'm going to trace all methods being sent on all objects of the baffle word class. Instruments creates for us a custom instrument here in DTrace. Let's take a quick look at that.
So when you say trace a symbol, you'll see that it creates two probes for you, an entry and a return. You'll see that the provider is the Objective-C provider, the class is the baffle word, and the method here is the asterisk, meaning we want to trace them all. Upon entry, we save off the start time and the object ID pointer here in our action.
And on the return from the method, we will be sending some information to Instruments down here. And that's the self pointer that recorded during the entry and the duration of the call, which is the current timestamp minus the time that the return probe fired. Now what we are going to be missing here, and I want to add, is because we're wildcarding this, we don't know which method is actually firing. So we want to send that piece of information to Instruments as well for recording. So I'll go down to here to record the following data. Say record in Instruments, and then choose from the list of options here, the function.
Now in the Objective-C provider, the module is the class, the method is the function, and the name is either entry or return. So function is definitely what we want there, and we'll save that. So let's target our running baffle Cocoa process. And we'll record the trace. Go back. Now I'm going to run through a game here real quickly so you can see some trace data.
Unfortunately, I'm not very good at this, but I've got a paycheck riding on it. Okay, that should be enough. Now we go back here, we'll stop the trace, we'll take a look at what we got. So you see we have the caller, which is the call site, which is where the methods were being invoked.
We have the actual method, which is what I set up, the self pointer, and the duration. Now this is a lot of data. You can go through it with some filtering. And you can also go into the extended detail view to see a nice image of the stack. Click through here.
What we're looking for in our word is we want to see if the insert or remove methods are being called, specifically the insert, after we've made a copy. So let's go and we'll filter down to insert object in pieces. Okay, we see a bunch of hits there. And we see the last hit is at sample 502. So keep that in mind, because now we're going to look for the copies.
So we look with copy with zone. We see it happening in a few different places, here and here. Now the last one's at 5.03, so that's a good indication that we haven't actually modified any words after we made the copies of those words. So that's not likely to be the problem. So let me close our trace document and we'll take a look at our other guess. And our other guess was that when we go back here, the words themselves are actually being changed because the pieces are being changed.
So in order to look at that, what we really want to do is you want to see if a piece has been added into a word. And if that piece has been added into a word and then somehow that piece changes, you want that flag. Pieces, of course, can change because you get to shake the board as much as you want.
But if those pieces are actually part of an existing word somewhere in the document, you definitely want to have that flag instead. So I created an instrument ahead of time here. So we're going to call up Instruments again. I'll go to my Word Corruption Check instrument, and we'll take a look at how I built that.
So using associative arrays inside DTrace, what we can do is on the entry to the insert object in pieces, we can take that piece object that was being passed into our word, and we can record it in a global associative array. So now we know that, okay, this piece object ID is now being used in a word somewhere, so let's increment a counter, and that's here in our used in words global variable. So we can see that we have a function where arg2 is the first argument to the function, which is actually object being inserted into the word.
And we'll just pass some information there for tracing saying that we're tracking a piece. And then for completeness, we'll go down to Remove Object from Pieces in case the user backtracks. We don't want that piece to be wrongly flagged as being part of a word, so we'll just say that we're dropping the piece. We'll go into our Used in Words global and remove our reference count there.
And then finally, those, by the way, those methods are being set inside the baffle word class. It might have been obvious, but I figure I might repeat that. But the, now the new probe that I want to put in here is in the actual piece itself, because I want to track any time a method that starts with set is being called on a piece. But the predicate suggests that it should only fire if the used in words contains that guy and the count is not zero. So if a piece is being referenced, that will show up as a non-zero number and this probe will fire.
So let's take a look at that and see if the problem is actually changing pieces inside of a word. So we'll attach to our baffle_coco process again, hit record. I'll run over to our baffle process, we'll start a new game. Can I buy a vowel? Okay, here we go.
Okay, now let's take a look at what we recorded in Instruments. You'll see that the string I recorded for what I'm doing here, my event string, tracking pieces, is getting recorded. We're seeing inserts firing. We're seeing the object ID of the piece. But we're not seeing our message. So maybe that is actually happening when we shake. Let's take a look at that.
See now there's where that probe is firing. And you'll notice the set methods being called are set visible letter. So that does indeed seem to be the problem. So let's go back to our code here, see if we can find that problem. Now I was saying that I had merged some changes in when they had added their feature, and my features that I added had to be, were actually related to that.
But I realize now that, okay, when we do make the copy, we do need a deep copy on this. So let me go back into Word. Baffle Word Class. We'll go to our copy with zone method here. We see that yes, I'm adding the piece to the array directly. That's probably not a great idea. So let's make a copy of the piece.
[Transcript missing]
All right, now we're going to hit record again on this new process. This is a neat feature in Instruments is that it will look for a process of the same name. Since the other one I quit, it'll say, oh, OK, here's one. Is this the one you want?
It's a new process ID. Say, sure. So now let's go and test that theory again, now that we've fixed it. And again, we don't really need to create any sort of real words here. We just need to get to the end of the game. Watch the sands run out.
Okay, now we can shake it up again. And let's see if we have the problem. We see tracking piece, and then we see dropping piece, but we don't actually see the error that we had seen before. So it looks like we fixed it. Now, with that in mind, you can do a lot of really advanced tracing here with assertion checking and building custom instruments to look at the behavior in your code, especially if you're doing a lot of programming by contract. Say you're looking at a delegate and you want to make sure that the delegate's D-alloc is never called before you've set the delegate to nil. That's an example.
And all this stuff really works great on the Mac, but unfortunately the D-Trace facility does not exist on the iPhone itself. However, this does work in the iPhone simulator. So let me quickly show you how you can launch the touch version of our app. And that will start it up inside the iPhone simulator.
I'm going to run through that one more time. Now, the Cocoa version and the Touch version share a similar code base. And you can see the probes firing. Now I hadn't made the change to the touch version, so we should still see the error. Okay, create a new game and shake.
Go back here to Instruments, and we see that our probe with the referenced piece modified is actually still firing even inside of an app in the simulator. So that's the end of the demo for this. I'd like to call Dave back up here to talk about UserLance Static Probes and DTrace.
Okay, very good. Thanks, Chad. So this is really nice being able to just put probes on functions and methods in your code, but what if we actually want to add instrumentation directly into your source code? How can we do that? So we're going to talk about DTrace static probes. We'll look at what are static probes. We'll talk about some places that we've added static probes inside of Apple's frameworks so that you can gain benefit from that. We'll show how to add static probes to your own code and then to use those static probes.
So what are static probes? Well, these are you want to come up with semantically meaningful probe points that you would put in your user space code. You don't want to just have them necessarily be the same names as your functions. You want to decide what your operations are that you're trying to trace and have probes that are named based on that. This way, if you change the function, you're going to have a name based on that. So if you change the function names, then the probe names are still nice and stable and your scripts and instruments will continue to work.
Static probes give you a great way to do tracing and logging. We like to think of it as any place that you might have put an NS log statement or a printf. You could use static probes that you could dynamically enable if you need them at runtime. Again, if they're not in use, they're zero cost.
Static probes will provide us a way that we can record Objective-C object descriptions as probe arguments, and we'll look at that. You can focus on just one process with these, or if you're putting them into a library, you could look with an instrument at all the processes that use this probe. For example, we have probes in Core Data. If you wanted to look at the begin fetch operation on all processes, you could use Core Data star colon colon colon begin fetch. The star, again, this includes the process ID and the provider name here.
So, static probes in Apple's frameworks. We saw the pseudo DTrace-L in my earlier virtual demo. You could grep for a specific process ID and see what static probes are in that process from this. So, for example, if you do this on Safari, you'll see core data probes in that.
With Leopard, we had static probes that we had implemented for what's called the standard DTrace P-Lock stat provider. So, this is P-threads information here looking at locking behavior. We have probes on core data. Spotlight provides probes in the MDS daemon. And we had static probes on the scripting languages. Ruby, Python, and Perl. So, you can see what's going on in those.
For Snow Leopard, we're investigating static probes in more places in the system, including Grand Central Dispatch, as Leanne showed in her demos in the Instruments session. and Dan Pettit are the team members. They'll be working with us on the application and system development side of things. They'll be working with us on the application side of things.
So looking at the Core Data static probes, we can see a pattern here that there's a begin and end probe for a number of different operations in Core Data, such as faulting, faulting with cache misses, relationship faulting, relationship faulting with cache misses, fetching, and saving. And it's recording the relevant arguments in each case. So you could actually write a fairly simple DTrace script that would actually capture all of the information for what's going on with Core Data in your entire process with just a few printf statements here.
But we've actually made these core data probes a bit easier to use in Instruments. We've got custom Instruments already built into the Instruments library here, so several different types of core data instruments. So, if you want to write static probes for your own applications, what do you want to think about? Well, you want to identify what are the interesting operations you want to trace.
A lot of times you'll have, for example, fairly expensive things or things that take differing amounts of time, and you typically want to see a probe at the begin of that operation and at the end. And then you might also want to look at progress along the way, because there might be meaningful points where, you know, if I'm processing 10 files, then tell me when I've gotten through each file.
At each of these probe points, you want to think about what is the interesting data that you would want to record at that probe point so that you could write scripts with it to get log messages out, or display that information in a detailed view in Instruments or graph it in the track view. And then you want to tell the clients of your probes what your probe points are.
So, the series of steps you'd go through to add static probes to a process is first write a provider description file, then set up the build dependencies by referencing the header file for that in a source file. We'll build it to generate the header file, and then add the probe invocations to your code. Amen.
So we're going to take a look at an example here. And you know, Chad's paycheck really is depending on how good he is with this Boggle game. And I'd like to be able to study this a little bit. So I want to put a probe on when he starts the word, as he's going through, hitting each letter, and when he ends the word. So I want to be able to see what the timestamps on all these are and what letters he's looked at along the way.
When we're recording data with probes, in the DTrace language, the probe argument types must be C data types such as ints or shorts or longs, char star, void star. If you want to record Cocoa object descriptions, here's your opportunity to do that. You would need to record those object descriptions, convert them into char stars by using UTF-8 string and then casting them.
So our second step here is to reference the header file. So in our example here, we see that the gamecontroller.m source file, we're adding an import statement to import bgbaffleprobes.h. The Xcode build system, if it sees a reference to a .h file, it knows that, oh, okay, I see a .d file of that same base name, so I know how to generate the .h file. So step three is to just build, and that would generate the header file for you, and then code completion could be used.
If you're using a make-based project, you can add a reference to the header file. So the next step here is to add a rule to your make file using DTrace-h, where the -h says generate a header file using this source file name, the .d file, and write it into this -o output file name.
So I've described here the way that this should work, and it sometimes does work, but it's slightly buggy with the Xcode build system dependencies right now. We need to fix that. Chad will show you how to work around that issue at the moment when we do a demo. Amen.
The header file that does get generated, it's not really meant to be human readable. A large part of it is fairly obtuse. The important parts of it is that it takes your probe name, such as start word, and it generates macros for that. So the form of the macro is the provider name, then an underscore, and then the probe name with everything converted to upper case. So you don't want to use a probe name that's like start dash word because when you use that in source code, of course, that would look like a minus sign. So it generates two macros, baffle start word and baffle start word enabled.
Now I can go into the source code and add probe invocations as my final step here. So, in the baffle method, add visible letter of piece, if I look at the array of touched pieces that I've got, if I don't have any yet, if the count of that array is zero, then I must be starting a word and I can call the baffle start word probe.
Then after I've added a letter in, any letter, I can go ahead and invoke the baffle word progress method, passing in the word up to that point. And you can see we've done the UTF-8 string conversion. And finally, when we are done and we commit the word, we can put the baffle end word probe in. Now you may be looking at this saying, whoa, you said this was zero cost if it's not in use.
And you can see we've done the UTF-8 string, that looks like it could be kind of expensive if I'm not using it, and that doing a count on an array, I mean, what's up with this? Well, that's where the isEnabled probes come into action. So, DTrace offers these isEnabled probes to say, only execute the code inside this condition if the probe is actually enabled at runtime. So, we can surround the baffle start word and baffle word progress.
So, we can do that with a couple of snippets of code with an if on that condition, and that converts this just into one quick test and branch at runtime when the probe isn't enabled. We don't need to do that with baffle end word in this case because there's no argument marshalling code, and we just have a couple of no ops in the code when it's not enabled. So with that, I'd like to bring Chad back up to add some static probes into his example so that I can watch his progress here. Thank you, Dave.
Alright, so this got a lot more exciting for me. Okay, so I have my baffle word, I'm sorry, my baffle Cocoa application project up here in Xcode. And we've created the file ahead of time with the descriptor. I'm just going to-- the descriptions of the static probes, I'm going to drag that into my Xcode project here. Add that to the current target. So let's take a quick look at that. That's the provider's baffle and then the probes are defined. It's a very simple syntax.
Now, we talked about using code completion, and there is a situation where the header file doesn't exist yet because it has to be built. But if you want code completion to work right out of the box, you can come over here to select the file, the .d file, and then say build and compile.
And that does actually generate the header file for you. So when you come down to the site where we wanted to add these probes, which is in the game controller, If you import your header file, then when we go down to the sites where we want to add the code, the code completion will work for you. Because those macros can be a little hard to type in by hand. So let me show you that. See, so you got all the code completion after I hit the compile in the .d file.
Now, someone in the code was nice enough to leave a comment behind saying where I could insert this to find out where the beginning of a word is. So we'll use that. Now this is just the code that Dave showed you on the slides for starting a word, doing our test with the is enabled and then the start word probe firing. So skim down through the code. Oh look, another comment.
Okay, this is the word progress. Looks like somebody thought we were thought ahead of time when they were commenting the code. This is the one we have the UTF-8 string conversion on the current string of that word. And then inside the commit word method here, we're going to go to the word has ended and add in our end. Actually, that one I could probably type in my hand. Endword of my code completion.
Okay, now let's compile and build that up and give it a run. Save the file. Good, so now we have an application in there with static probes. So we went from having no probes at all to a fully instrumented baffle game of death for me. So now I can start Instruments. I can go to a blank template.
We created an instrument ahead of time to look at our static probes called Word Progression. So let's go in there and take a look at that in the DTrace instrument builder. So when you specify a static probe, you come in here to the type of custom. And you specify the provider. Now your provider as a DTrace static probe, when you do say a DTrace-L or you look at it here in Instruments, it will say baffle, which is the provider name, plus it'll have the PID appended to it.
When you're specifying a custom one inside Instruments, you want to say baffle star. You don't have to worry about it maybe picking up probes and other processes because if you target a process in Instruments, it'll do the filtering for you. For this particular probe, I record the probe that's firing in Instruments, and part of my action is to record the timestamp of when it starts.
As the word progress continues, we just simply put a record to instruments action here that says take arg0, which is that string that's being passed in. We want to treat it as a string. Now, you should note that when treating something as a string, let's say coming right in from Arc 0, when we generate the DTrace code, it actually does a copy and stir and all of that's managed for you. So you can say, Arc 0, it's a string. Please send it out to Instruments. And that's what we're doing here.
And then down here on the end word probe, this is start word, this is word progress, and then this last one is end word. So at the end word what we're going to do is send the current time minus the start time out to Instruments and call out duration. So let's send that, or let's point that at our Baffle Cocoa instrumented app here. We'll hit record, go back to Baffle. Now I'm going to need some audience participation here. I'll see how if I can do it.
[Transcript missing]
All right, I got busted. Okay, going back to Instruments, let me stop the trace. You can see the call sequence. You can see start word probe firing, and then the word progression here, and then how long it took me to complete that word in milliseconds because Dave really likes his accuracy.
One of the really neat things about this is it looks like an alternative for replacing logging, and in some ways it is, but there's not many logging features that can actually give you the stack trace of when that log message fired. And that's something really interesting that you can do with DTrace static probes.
In addition, you might notice these fields are left blank. If you have a static probe and it's used in several different functions, you can actually specify the function that you want that specific probe invocation in. And also in a specific library, if all of a sudden your code is kind of migrated to a few different libraries, you can specify that there in the descriptor. But that's basically how you would get up and running. It's very simple. The workaround that Dave was mentioning is really just a quit exercise.
You can just go to the DTrax code and then come back in. And once you do that, if you modify the .d file, it'll generate the header, and then the header will cause any file that references it to recompile. But we're going to work on that, and that's the end of the demo, and hope you guys have a good rest of the week. I'm out of here. Dave, come back up. Thank you.
Okay, very good. So to recap one more time, tell them what you're going to tell them, tell them and then tell them what you told them. We added static probes by writing a provider description file, by adding a reference to the header file for that descriptor file in our source file. We generated the header file by doing a compile on the .d file, and then we added the probe invocations to our code.
Then, an additional step, you might want to create a custom instrument in Instruments to use these static probes as well. So in summary for our session, hopefully this has given you some new ideas about new ways to understand the behavior of your application. So this can span the range from classical debugging and logging on through to performance analysis.
We looked at how to trace functions and methods, both a specific function as well as using wild carding. For example, on the set methods on properties, you can look at accesses on synthesized properties that way. Pretty cool. We looked at building custom DTrace-based instruments and then building our own static probes and using those in our source code.
For more information, you can contact Michael Jurowicz, our evangelist. He'll be on stage for Q&A in a moment. You can look at the general documentation for the WWDC, also the DTrace documentation at the Sun website. And I noticed in the introduction to DTrace session yesterday that Steve Peters had a number of additional reference materials at the end of that session. So perhaps you caught some of these earlier sessions.
But if you didn't, you'll be able to go back on the videos and look at these. Getting started with instruments, debugging and profiling your iPhone application, using DTrace on Mac OS X, and then also performance tuning your application with Shark, which is a great CPU profiling tool that can do very fine-grained profiling of your application.