Development Tools • 58:42
Advanced debugging requires a complete understanding of your application: its memory usage, tracing events, performance impact, and the relationship to user actions. Xcode's new visualization and tracing tool integrates many of today's familiar performance tools along with a new Mac OS X version of Dtrace to provide unparalleled insight into the behavior and performance of your application. This session will show you how to get the most out of your code using this revolutionary new tool.
Speaker: Steve Lewallen
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it may have transcription errors.
Okay, so welcome to today's session on X-Ray. My name is Steve Llewellyn. I'm the lead engineer on the X-Ray app, and it's my pleasure to tell you today where we currently are with X-Ray and the Leopard Preview. So X-Ray is a new developer tool aimed at allowing you, the developer, you, the QA engineer, you, the IT support person, to peek beneath the covers of one or more running apps on the system and to gain an understanding of their behavior. It's also aimed at allowing you to communicate that new understanding to others on your team and your extended team. So today we're going to cover the problem that X-Ray is aimed at solving or helping you solve. We're going to cover why X-Ray is the solution to that problem, a little bit about the X-Ray architecture, we think it would be a little bit helpful for you to understand that, and we're also going to cover how you would create your own instruments. Instruments in X-Ray are the central theme. They're the technology that you use to gather data on any particular subject matter you want in your program.
We also will discuss how you create X-Ray templates, and finally we'll discuss how you use X-Ray with an Xcode. So what's the problem? Well, systems today are growing increasingly complex. We live in a world where it's great that we can get a system with multiple cores on even the simplest box. We live in a world where even the simplest client application actually is in a client server environment. The Windows server is doing your graphics, for example.
And the methods we use to test these applications, black box, white box testing, They're great, but they can actually cause us to miss certain problems. Let's say that you add some new feature to your app and you and your QA engineers, you test that feature and yes, it does steps A, B, and C, looks great, doesn't crash, ship it. Well, it may be showing other signs of trouble that you haven't noticed with your normal testing. Maybe it's using more memory than is desirable, not leaking, but just it's now gone above a certain threshold that you really intended to not go. We as developers, we try to check these things, but we do so many -- write so many lines of code and add so many features, sometimes we can miss these things and only catch them a lot of times just before we're going to ship, for example. Another problem is that you can focus on too small of an area. You can be looking at a particular API, that API is beautiful. It does everything you wanted it to do, but when you deploy it in a framework that others use, it then has other side effects you didn't anticipate.
And the tools we have, we have great tools on Mac OS X that are very powerful to help you analyze your system, your processes, the performance, memory usage, etc. But they are each different. And we're forced to, as developers and QA engineers, IT support people, learn each of these tools individually.
And then we're also forced to correlate the data they generate. They may generate very powerful data about one specific kind of performance data, for example, but not another. And you, the developer, you're forced to correlate that data in your head, if at all. And that proves to be very difficult. And finally, as we all know, and we as Apple engineers know every year at WWDC, you can have an application that performs beautifully in the lab, and you bring it out into the real world, and it has a problem. So it's hard to, A, forecast that problem, and B, somebody remotely will try to describe what happened, and it's hard to understand and reproduce. And this is just all part of this growing complexity of systems. So we think that X-Ray is the solution to this complexity.
For the developer, first of all, X-Ray provides you the ability to-- well, it makes it easier or not as difficult to test not only your features, but test the features of other developers, you may have inadvertently affected their code. I know I've done that. I know other people have done that to my code. So it's great that X-Ray can help you avoid those things. It can also help you to discover other semi-related but not directly related issues, things that just go out of bounds again. And so you don't have to always be focusing on that, but X-Ray can sit there as a partner with you and say, you know, something else is going wrong. You said this was critical, and you better look at it now. It also allows you, X-Ray does, to communicate to your QA engineers. Whenever you add a new feature, what do you have to do? You have to go and explain how you use that new feature to the QA engineer so they can test it. Well, X-Ray allows you to automate that process, and it also allows you to automate the process when you're discussing it with the people who do your publications, the docs for your app. You also, when you add a new feature, need to describe how to use it to them as well so they can document it. Now you can use x-ray to actually show them by proxy how to manipulate your new feature. And it also allows you to, well, it's like a medical analogy. You know, you go into the emergency room, hopefully you haven't, but someone goes in the emergency room and what do they do? They hook up a heart monitor, they look at your blood pressure, they do all these things. Those are the vitals of a human being. We each know that there are vitals of our own apps. I know that I had, before X-Ray, built into my different apps custom instrumentation to make sure, oh, the major objects are going away. Oh, we're closing down this system when we quit. Those sorts of things. So you can build in some watch points with X-Ray to help you keep track of those vitals. You can even pass them off to other people so they can track those vitals as well. So the solution to this complexity is X-Ray for QA engineers also. They can, as you did, use X-Ray to automate the testing.
So let's say that a QA engineer is doing the testing on a network application, a browser, for example, or something else, maybe something in a handheld device or something. And they want to keep the network traffic down. They've been told that this app should have such and such network traffic load and that's it. But they've also been given the task of, you know, a developer added some features and I need to go through and press all these buttons and make sure it works. Well, X-Ray will free them up so that they can use their engineering skills to think more about the other potential problems that could arise in the app due to the changes the developer has made and let X-Ray press all the buttons and do that type of manual labor. And finally, if they do discover a bug, they can actually say, you know what? Instead of writing this bug report, step one, I press this button. Step two, something weird happened over here.
Step three, I press this other button and sometimes it crashes. They can actually record via X-Ray how they manipulated the app and just send that recording back to the developer and let the developer just hit one button and see it happen right in front of them rather than trying to interpret. I know that I've gotten bug reports before where I say, that's not even actually possible to do. So I have to send it back and say, you know, can you clarify this? A lot of times we all get in a rush, right? And we say, well, I can't reproduce that, so, you know, enough of that bug. And then it comes up later on and you wish you would have spent more time looking at it. So in addition, the debugger, the QA engineer can use those vital signs I spoke of earlier that the developer created for himself or herself and use those on the side while they're doing these other tests and they can go back and say, you know, engineer A, when I was testing your features, the vital signs monitors that engineer B gave me to make sure we're always working right, they're not working so great anymore. And maybe you want to look at your change in light of that new information.
And finally, for the IT support guy or girl, you're out there maintaining a network of machines, and you want to monitor the load on the machine-- CPU load, the network traffic, disk usage, et cetera. You can use X-Ray to do that as well. You can also leverage, again, those vital signs. Maybe they've been passed on to you, or maybe you're having problems in the field, and so the developer provides these to you and says, Well, run this and tell me what it says. And then you can also, as the QA engineer did and the developer, make a recording of something that shows these things going awry and send it back to the developer. And he or she can reproduce the problem right there. So now I want to talk about the X-ray architecture a bit. I want to do this because I want you to understand that X-ray is technology agnostic as far as what it uses to gather data. So X-Ray is built out of a series of plug-ins. And a major set of plug-ins are instrument plug-ins. Instrument plug-ins can actually supply more than one type of instrument. And a plug-in is usually organized around a particular technology that is used to gather data. So one of the technologies I'm sure you've all heard about is D-Trace.
So X-Ray uses D-Trace to provide all sorts of instrumentation focused right now on the file system, for example, and memory. If you were at the keynote and attended other talks, you've heard about garbage collection. So X-Ray includes a DTrace-based instrument to allow you to look at how garbage collection is working in your new garbage collected app. And we also build all sorts of other instruments with DTrace. And in fact, you can build your own. And we'll talk about that in a little bit. We also have things that are more familiar to you. I'm sure you've used our Object Alloc tool. And now we have an instrument based on that same technology. We also have a great technology from our Automator group. This is the technology that allows us to record things happening in an app and replay them later. And we've built that in as an instrument in X-Ray. And finally, we have instruments that allow you to look at general resource usage, CPU usage, disk usage, network traffic, et cetera. So I've talked a little bit, and now I'd just like to give you sort of a grand tour of how we use X-Ray so that you can understand some of the concepts. Over to the demo machine, please.
Okay, so I'm going to start up X-Ray, just have it here on my desktop. The window you see before you now represents a trace document. So you can have as many of these open as you'd like. This trace document is where you will decide what it is you want to trace, the particular elements of that, say, process you want to trace, and this will be where you will decide how you will look at the data returned card, and where you will search and filter the data given to you by X-Ray. So in the bottom of the screen, in this area here in the lower half, this is your instrument toolbox. Now X-Ray comes pre-bundled with a host of instruments, and by the time Leopard ships, these will be richer instruments, probably have some different instruments as well.
In the upper left section of the screen in the trace document, this is your instruments list. So we have instruments in the toolbox on the bottom, but we have not yet applied them to the trace document. So we can't perform a trace yet. So in order to go further with this tour of X-Ray, I'm going to look at the resource usage of Safari, something we saw some of in the keynote. And then I'm going to go further and show you more about each of those instruments.
So I want to look at memory usage. And therefore, I'm going to select my object alloc instrument. And I'm going to drag that up to my instruments list and deposit it as so. I also am not interested in the UI recorder at the moment, that technology from the Automator Group. So I'm going to collapse that, make some more room for me. Also, I want to look at file activity. Let's say I want to see what files Safari opens and closes. So I'll take the File Activity instrument, and I'll drop an NSO. And finally, Safari is a network app, right? So let's look at network activity of Safari.
and I'll drop that in as so. Now I can actually run a trace. To do that, I press the Run button that's square in the middle of the window here. I'll press that now. Now I'm presented with this dialog. X-Ray is asking me, well, what do you want to trace? Now it so happens that for many of these instruments, you can trace all the processes that exist and will exist on your system or a particular running process already. But in this case, I have it set up, which is the default setup, to ask me to trace one process. So I'm going to select Safari. It's not running yet. It's going to launch after I hit the Open button. And I also want to point your attention to a few other things in this dialogue. So we're all developers, so oftentimes we have special environment variables that we can set to change the behavior of our application. So you can do that here in the environment variable box. You also may have command line arguments you want to pass. You can do that in the arguments section.
You can also decide, well, when I end this trace, I want to also stop the application. That's the common case. So by default, this checkbox here is selected End After Tracing. So when I press the Run button again, which will mean stop the trace, it will actually stop Safari in this case as well. And finally, X-Ray can actually allow you in one trace document to trace multiple processes. Let's say I had a new client server solution that I was working on and I wanted to trace memory usage in both of these processes.
I could use ObjectAlloc, for example, on the client and the server and I could use the checkbox here, apply to all instruments, I could actually deselect that, apply to ObjectAlloc instruments and when I hit run, it would have asked me, okay, what application do you want to launch for the first instrument and what application do you want to launch for the second instrument, and I would see all of that in the same window, which is really great, especially since X-Ray provides this over time readout that we'll see, so you can visually even correlate the data coming back for that solution. And so I'm just going to accept the defaults here, so end after tracing, apply Safari to all instruments. I'm going to hit open.
Now, it's going to prepare all the instruments and it's starting to run. Safari is bouncing and launching. And when you are applying several instruments, obviously your process, depending on the instruments, may slow down a little bit. In this case, Object Alloc is taking up some time here, the Object Alloc instrument. But we have now Safari. It's almost done loading.
Okay, it's finished. And in the X-ray window now, we see to the right of the instruments, graphical displays, one for each instrument. This is your high-level view of the data coming in to X-ray from the instruments. One way you can think of this is a navigation tool to say, "Oh, I see a general problem here in this graph. Let me look at a detail view."
You can also look at tracks in different ways. So I have the object alloc instrument selected. Maybe I wanted to see the call stack depth on each object alloc event. That's freeze and allocs and all sorts of different things. So I'll select my track style pop up. You have this in each instrument.
And I'm going to say stack depth. So now I can see the actual stack depth of the various allocation events. In this case, I want to go back to the total bytes graph, because I have some other things that I'd like to show you in this particular instrument. So when I select a detail view or an instrument, the lower part of the screen, the trace document, changes for a detail view of the instrument selected. So you notice it was changing as I was selecting different instruments. So now I have the ObjectAlloc instrument selected again. In ObjectAlloc, the detail view allows me to do different things. I can sort on different amounts of data, and I can see the different categories of objects created. When I select different categories, and I'm actually going to stop this trace now because I want to keep these labels here where they are so I can speak more to them. When I select a particular category, I can go into one. Say I wanted to look at all the CF set events. I can click the small eye icon by that category. I'll do that here. And now I've drilled down into that particular category of allocation events. And I can see freeze, and Alex, et cetera.
And I can also look at extended data. Where, for example, did these events take place? If I press the E button, the extended data button, on the far right middle control bar-- I'll do that now-- An extended detail view for the particular event is displayed. And as I go down these different things, we can see the stack trace change reflecting where that event happened.
So also on screen is at the very bottom of the detail view a navigation bar. This shows you where you are in your detail view. Different details could have different levels of categories that you could pursue. When you want to go back up a level, all you do is select the previous level. I'll do that as so, Object Categories. And I'll also collapse the extended detail view. And now I'm back to where I was. Now, another thing that you may have noticed is that tracks have different flags. In this particular case, I'm manipulating the inspection head. This is showing me for each particular track of data what is happening at that very moment in time, what event is nearest that moment in time, and pointing out in several of the different instruments more interesting information. For example, in the object alloc instrument, it's showing me a peak of memory that was total bytes allocated versus the amount of bytes allocated for, in this case, the immutable CFString. Now some of you may not be able to see that, but that's a small red line at the bottom.
Obviously, any particular object as compared to all the bytes allocated is probably going to be a small amount. If I wanted to bring out that detail, exaggerate the changes in it, I can actually use the deck height control in the instrument. This is located in the far right of the segment control for that instrument. That's this with the little plus sign. I can press it to increase the deck height and bring that detail out. Now we can see that CFString is more pronounced. If I wanted to shrink it, I could do, holding down the option key, the button will change to a minus sign and I can shrink it. And I could also go to the view menu and decrease the deck size or increase, as you see in this menu item, to shrink it further.
So let's look at another instrument. The File Activity instrument is showing me all the opens and closes and stats on various files. This is built actually with DTrace. And I could filter this on various types of data. Let's say, for example, that I wanted to look at all the opens. So all the files that were open.
Well, I'll click on the Search field in the lower left-hand corner of the screen, and I'll type open. And I'll hit Return. Now, it's filtered all the events to open. It's also done something a little unusual. It's tokenized that open string. The reason it's done that is we want to allow you to filter on more than just simple string data. For example, if I reopen the extended detail view and I click on various file activity events, I see something kind of interesting. It looks like our symbolication here is having an issue.
Let me filter that out a moment. This will still actually work to some extent, but that's unfortunate. Okay, well, I'm going to try to do it anyways. Basically, what you can do is you can select multiple stack frames in your event, in your stack trace viewer, and if you hit the spyglass icon, it will filter down to just events that include that bit of stack trace. I'll do that now, and the events did change, but obviously we're getting a lot of bad symbolic data here right now. I apologize. So you can filter the data in multiple ways.
So I'll just clear that. and we will move on. So another thing that X-Ray can do is show multiple runs. So You may want to see the before and after effects of some change you make. So X-Ray allows you to visually compare those. You run it, you make a change, you run it again, see what happens. So if I select the Show Filters button, this is this middle button, the segment control, for various instruments, and press Run again, Then I will see Safari will start up again, and I will see a second run for these instruments become visible. And actually, I'm going to shrink these down some so you can see them all on screen at once. So now I can select different tracks of data and compare them visually. So let's stop that and quit X-ray. And let's go back to the slides please.
Slides, please. OK, so let's review the concepts that we saw. First of all, we learned that there's a trace document that you pretty much live in to trace any particular subject matter. And you can have more than one of these. We also learned where you get your instruments, those devices, software, pieces of software code that capture and display the data to you. You get those from your toolbox. You also have a list of instruments. This is the instruments applied to the trace document. Those are the instruments that gather the data. And to the right of those are the track views, the graphical views that display the data.
And finally, we learned that you have a detail view. And if you select a particular instrument, the detail view of that instrument will be displayed. And we also learned that you have multiple run support. You can see each run individually or as a group that you've performed. And now let's go and look at how you create an automated test case. I spoke a lot of that talking about how each of the different groups of users could take advantage of X-Ray.
So we're back to the demo machine. And let me start up X-Ray again. And this time, I'm going to apply again our old familiar instruments. and I'm also going to start recording. Now, when I record a master track, I'm not gathering data for the instruments in the list above.
So I'm going to press this record button that is a bit to the left of the run button we used earlier. I'm going to press record and, oh, it's asked me, it said, you know, your recording is unavailable. Well, this technology comes from our Automator Group. They use the accessibility API to make sure that they know exactly what you are manipulating. And so I'm going to go down to universal access. And I'm going to enable assistive devices.
If you can't play back or record, that dialogue should have opened up. But if not, just go there and make sure that that is working. So I'll hit the Record button again. It's going to ask me to select an app I want to record. And I'll select the good old familiar Safari.
and I'll do a few things. I'll open up the bookmarks group and I'll add a new bookmark group, my bookmarks, hit enter. Oh, I decided I didn't want to do that and I'll close the bookmarks group again and I'll quit Safari. Now, what we see are a series of events gathered for that recording. I'll stop the recording now and now I can replay the recording and and at the same time run those other instruments that I had to gather data based on that. So all I need to do now that I have my recording is press the run button.
It's going to start up Safari again. Now, the recording and playback framework is smart enough to know that when you're using other instruments, the timing and such may be different than when you made the recording. So what it does is it keeps a good eye out for the elements, the visual elements that you manipulated, to be available before it tries to replay those events. So it's typing in my bookmarks now. And I'll delete it. and close the bookmark screw, the panel, and quit Safari. Okay. So that is using X-Ray and that record and playback technology to automate your workflow. You can imagine doing that for different types of tests that you perform. Okay, so let's go back to the slides, please.
Now, just to review, it's very simple to make a recording. You just press the recording button. You manipulate your app. You press stop. Usually, it's a good idea to quit your app before you do that just so you can make sure it's always in the same state when you get back to replaying it. And another thing that you can do that we didn't see is to actually loop the recording. Many times, a problem doesn't surface just the first time you run it. Maybe you have to run it a few times. So X-Ray will automate that for you as well. You can just say loop this recording at playback, and it will just keep replaying the recording. That's one of the reasons it's good to quit the app at the end of a particular recording.
So it will play it through once, quit the app, start it up again, play it through, quit the app, et cetera, and keep running until you hit the problem you were looking for. And finally, you can save the recording in a template along with other instruments. So let's talk about X-Ray templates. So X-ray templates are X-ray documents pre-configured with a certain set of instruments to trace a particular subject matter. And they can include pre-recorded MasterTrak recordings. These can be anything you want, but generally people either have them be very general or specific to a particular problem.
So how do you use templates? Well, you can save as your trace document, select trace template-- we'll see how to do this in a minute-- and save them to disk. Now, trace templates, even if you have a URI recording which have some binary data encoded, are basically flat XML files. You can check this into a source code repository. You can email them to someone. You check them into your own project, et cetera. So you can easily pass these around.
And they can also include instruments that are not in your own toolbox. So someone could make a recording and put in a custom instrument and send you that template. You don't have that instrument. As soon as you open that template, that instrument will appear in your toolbox. And actually, you'll be able to use that instrument for other things as well. So it's a great way just to pass around custom instruments you create. You can also double-click these templates as if they were applications. You don't need X-Ray running. And X-Ray will pop up pre-configured with these instruments. And finally, and we'll see this later in the demo also, is that you can drop these custom templates in library preferences x-ray templates. The x-ray templates part won't be created on your system. You'll have to go and do that yourself, as you have to do in many different preferences apps. But if you drop that in there and then you relaunch Xcode, you'll find that template in your debug performance tools menu, and you can use that with your own app. So now let's look at templates in the ER recording.
So I have my existing application here in this recording that we made. I'm going to go up to the file menu, and I'm going to say Save As. And I'm going to go to Desktop, and I'm going to say, save this as a trace template. And I'm going to say My Trace Template. Okay, and I will save that.
Okay, we see it appear at the bottom of the screen. I'm going to actually quit X-Ray now, so X-Ray isn't running, and I can double-click on my template. It's pre-populated with instruments in a U.R. recording I had before, and I can press the Run button again, and then again it will start up Safari and run through the recording, and I'll let this get started, and then I'll stop it so we can move on. So it's launching Safari. And it's starting to make the recording-- or starting to play back the recording, pardon me-- type in the keystrokes, et cetera. So I'll just go ahead and quit that now. I'll stop X-ray and I'll quit that. Okay, back to the slides again please.
So, another thing that X-ray has sort of become good for is busting your own assumptions. Bad assumptions are caused by lack of understanding of some subject. I make bad assumptions about code. I'm sure we all have. And bad assumptions lead to bad decisions, and then that leads to bugs. So one of the ways you can bust an assumption is for an IT administrator. So this demo I just put in here yesterday, I heard a story about this from probably someone in this room who passed it along to someone that I work with and it related to me. They're an IT administrator and they wanted to determine the configuration for machines that they should have deployed in their business or the university.
Basically, they wanted to determine what's the minimum amount of RAM and therefore what is the most efficient set of applications based on RAM usage that I could deploy with. One of the things they wanted to look at was web browsers. And I thought about that, and-- It has been drilled into my head for years and years and years that certain other browsers, say Opera, are really, really memory efficient and nice, small, compact browsers. And I thought, well, these guys are probably going to compare Opera to Safari and they're going to choose Opera. I don't want to show that demo. So obviously I checked this out ahead of time, but let me do a little demo to show you kind of the Swiss Army knife ability of X-Ray to bust different assumptions. Back to the demo machine, please.
So what you can do with X-Ray is compare different apps in the same trace. So I'll use our favorite old object alloc instrument again, and first I'm going to run Safari. I'll open that up. Have Safari and Opera set to open up the same webpage. Let Safari do its thing here.
Okay, it's loaded. Now I'm going to actually stop that trace directly like I was doing before by pressing the run button again. Now, a feature of X-Ray is to allow you to change the conditions of the trace after you've selected the first one. If you hold down the option key and you press the run button again with the mouse, it's going to bring up the application chooser dialog again. Now, we often use this just to change environment variables.
I remember I was working on some garbage collection stuff and I wanted to flip a flag to switch garbage collection on and off. That was a use of this. But I can just also choose an entirely different app. So I'm going to go to my desktop here and I'm going to actually choose Opera. And I'm going to launch that now. And it's going to do the same thing. It's going to load the Apple Start page.
and I'm also going to show runs. The previous trace is unlabeled, but it was Safari. It's not running now, obviously. In the primary trace, the top one is running. I need to go through, and I'm not a real Opera user, so I need to press this button for some reason.
Every time I restart. So it's going to load the Apple page. Wait until it's done. OK. And now I'm going to go back and, you know, son of a gun. I was actually wrong. That assumption was bad. Safari actually, as we can see, these are on the same scale vertically. That's the total number of bytes allocated. And Opera actually took far more memory. I'm still surprised by that because you get drilled in your head what is true and what is not. and that those assumptions can often be wrong. So that's an example of busting an assumption using kind of the Swiss Army knife ability of x-ray. So back to the slides, please.
So another problem. We've all had that moment where we're sitting in our office, boss walks in, and he or she clearly has this look on their face that they're going to tell you something you do not want to hear. And we may have also had the moment where they say, you know, such and such engineer has moved to a different group or left the company or something, and their application is not in such good shape. And I can't tell you anything about how the application works, but we really need this fixed because we need to ship this app ASAP.
So in this scenario, let's say that we have this vital app. It's called the Family Slideshow app. And yes, this is just an excuse to show you pictures of my daughter. But-- proud father. But remember, this is a critical-- the scenario is this is a critical app for the company. And the app has this slow, terrible animation. So you need to figure out why it's so slow. First thing you say is, this guy probably didn't use core animation. And you're right.
If I would have used that, I wouldn't have had this demo. So I had to cook something else up. So we have this app that has this poor slow animation. And we need to understand what it does and why it's a problem. Now, this obviously is a very simple application. But oftentimes, we're just given mounds of code. And we have no roadmap in that code, no way to understand how it works. So we need to use tools to help us. And in this case, I'm going to show you how we could use X-Ray to help us out. So let's go back to the demo machine.
And let's first take a look at that demo app. Let's just run it. So, okay, we can clearly see that it has very slow, very clunky animation. We need to figure out why that is the case. Now, as an X-ray user, I know that X-ray comes pre-bundled with all sorts of templates.
Well, a few of them right now. And, Maybe I can use one of those templates to help me fix this problem. Well, if I go under my Debug menu and look at my Launch Using Performance Tools submenu, I can see-- and obviously,.dsStore isn't a-- isn't a new tool that we're not telling you about or anything. So the three items above that, though, are actually X-ray templates. You just treat them as separate tools. So we have one that just looks at general file system monitoring, who's created what file, who changed what permissions, all that sort of stuff.
We have a memory analyzer that looks at regular memory, shared memory, that sort of thing. And we have one that will immediately start up the UR Recorder so that you can run your app and make your recording like we saw before. But none of these are really going to do it for the problem that I have. What I want to see is something that tells me, well, I can look in this list of code, it pops at the top, but where are these files coming from when the app is actually running? And the files, they look really large in my editor here. So that's just a huge picture there. So what's the cost of loading those images in? How long is it taking? How many bytes are actually being read in of those images?
How are they being used? So what I can do is create a custom template for me that also includes a custom instrument. The great thing about all this is that once I get done solving this problem, I'm going to have this template, and I'm going to have this custom instrument to help me solve other problems. So what I'm going to do is open up X-Ray. And I have to admit that when I practiced building this custom instrument-- you have to do some typing in it right now-- and I messed that up at least half the time. So as the Apple crew was reviewing my presentation, they kindly suggested that maybe I should have this pre-built for the presentation. So I took their advice, and I have it pre-built. But I'm still going to go through and take a look at that instrument with you, and I'm going to show you how you build custom instruments.
So if you go up to the File menu, you're going to see this menu item called Build New Instrument. When you select that instrument, this sheet's going to pop down. This is a DTrace instrument builder. That is the only technology we have right now that we can build custom instruments in the X-Ray UI for you to use.
Let's go and use the same UI to browse the pre-built instrument I have. So I'm going to cancel out of this. and I'm going to select Read File Sizes. This is its custom instrument. I'm going to go back, and I'm going to say, "Edit Read File Sizes Type."
Now, the first thing I want to do is work backwards from what I want out of this instrument. Now, I'm going to go through some detrace-isms, and I don't want you to worry about understanding exactly what that DTrace stuff is. There's another session tomorrow on the OS Foundations track, and there's documentation on the web to learn about DTrace. But what I want you to take away from this demonstration is that, A, you can create your own custom instruments.
B, they have certain components, and C, how to think about building your own. So in this case, what I want out of this instrument is to see the full path to images that are being read in. I want to see how many bytes I'm reading out of those images, and I want to see how long it takes to read those images in. So I need to think about what API I need to instrument to get that data. In this case, I need to instrument the open API to get the full path to the file that's being opened, and I also need to instrument the return of that same open API so that I can get the file descriptor, because all the other API I'm going to use are just going to use the file descriptor, but I don't want to look at that in the UI of X-Ray.
This pop-up here is my list of probes, a probe per function. So in this case, I have a probe for the open call. And I have some Descript that will be performed when this probe is fired. That is the conditions, which in this case are very simple, just that this API has been entered into. You could have more complex conditions saying this API has been entered into, and the path is so and so. But in this case, I want all paths.
So I want to scroll away the path passed in, because on the next probe of open, but this is the return of the open call, I want to get the file descriptor that's going to be turned from open and associate that with the path I saved off just a second earlier. Then as I said, I want to also record how long it takes to read this file in. Well, basically I'm going to make some assumptions here. I'm going to assume that as soon as the API that's using this file are done with it, that they close the file. So what I'm going to do is on the open, I'm going to set my time array, keeping track of how much time is being used, to zero for this particular call, along with a bytes counter. And then in the read API that I'll instrument, on its entry, I want to record how many bytes in sum-- so they may call this 10 times, so add all those 10 times up-- in total were requested to be read from that file. And finally, what I want to do is on the close, when the caller that's reading all these images closes a particular file, I want to generate some data that's sent back to X-Ray to display visually to me.
So I send three elements back, the path, the total number of bytes in K bytes, and the duration of milliseconds. And I also sum up that bytes counter in the end there. So I'm going to cancel out of here. I already have this instrument. Now, since X-Ray allows you to have multiple instruments, one thing that I'd encourage you to do is to take advantage of that and keep an eye out for other things going on in the system. Memory usage is a great thing, so I always want to look at object alloc and what it has to say. I don't need the URI recorder for this demo, so I'm going to get rid of it. I'm going to click on this X in that URI recorder instrument, and that's going to delete that instrument and close that track.
I also want to use an instrument that didn't quite make it out the door for the leopard seed. It's a sampler instrument that will A, look at when you get spins, an app starts spinning, it will sample that app. And also B, you can have it set to just continuously sample the app. I'm going to use B, continuously sampling the app. So I'll drag in my sampler. And I'm going to use that custom instrument that I just built. Okay, so now I want to use this pre-configured trace document from Xcode. So what do I do? Well, first thing I'm going to do is I'm going to go quit Xcode.
So I've quit Xcode. And I'm going to go up to my File menu again and say Save As. I have the templates directory already in my list box there. So it's the user account, library, preferences, x-ray templates. I'm going to give it a name. Slideshow testing. And I'm going to change it to the trace template file format. And I'm going to save.
Now I'm just going to go back and check that it's actually there. Here's templates directory again, and we see it, slideshow testing template. So I'll cancel out of that. I'm going to quit X-Ray now. I'm going to reopen my project that I'm working on, the family slideshow project.
So it opens up. And now I can go under the Debug menu and say Launch Using Performance Tool. And I see my slideshow testing template there. So it's basically a new tool for me to use. And I could use it for all sorts of things. So I'm going to select that. And when I do, X-Ray is going to open up. And it's going to begin playing the slideshow app and taking those measurements. So we still see that we have a problem.
and slow animation, and we see various pieces of data being gathered. Now, for a new instrument, X-Ray will look at the numeric data that you return and try to provide some default track styles for you. In this case, for read file sizes, there's the basic generic one of just dot, dot, dot. This is an event, this is an event, this is an event. That's not really what I want here. So I'm going to go and I'm going to actually select the kbytes parameter, and it will actually show me when it's loading in various amounts of bytes. And in the detail view of that, I see the data that I wanted to see. I see how many bytes are being read in from various files and the duration in milliseconds that it's taking.
If I scroll down here, I can see all the images being read in. Remember, these are complete reads. This is open, read all these bytes in from the file and then close it again. So we can see that these files are being read in multiple times. They're rather large, and they're taking 4, 5, 3, 4, 5 milliseconds each. So if you do that a lot, yeah, you're probably going to get something like this. But let's look at where the app is spending its time. So I'm going to stop that, and I'm going to click on my sampler instrument, the one that I said just didn't quite make it out the door in time for the leopard seed. And I'm going to click on my extended detail view. Now the sampler instrument is designed to be really simple, to just pick out those points in time that it found the most common stack traces with code that came from your project.
And it uses a new feature of -- well, all these features obviously are new, but it uses another feature we haven't discussed yet, which is flags. So you can actually flag events that you find in any instrument. And you may do this as a form of bookmarking. You'll say, "Okay, this is an interesting event. I'll flag that. I want to come back to it later." And then you'll go and find another one. But in the case of the sampler instrument, it's automatically flagging things it finds interesting for you. So if I pursue these flags by pressing this flag button, this right flag button, just keep pursuing down, I'm going to go to stack traces that I see are most common in the samples and ones that contain my source. And you can see the ones that contain your source where they have the little source flags. So one of the things it's spending a lot of time in based on what Sampler is telling me is this fetch image named API. So I'm going to double click on that and bring it up in Xcode. And let's take a look at this API. Well, this API is reading in an image every single time it's called. And it's called based on Sampler all the time. So we looked at the file paths of the previous instrument. Let's go back, the custom one that we created. And I can see that all these images are coming from the resources directory of that app.
If you know something about Cocoa and AppKit and how it processes resource images, you'll know that there's a simple API you can use to read in these images, and it will actually cache them for you. So I'll just go ahead and I'll use that one. I'll just say return and say this image, image named. And I want to use the name without the ending. So I'll say name, string, I'll use code sense here. By deleting path extension, yes, I want that, OK. And I'll comment that other code out so that we have that for future reference. And I'll save it, and I'll build that again.
Now, if you recall, when we looked at multiple runs, X-Ray has the ability to show you a run before and after a change. So I've made a change. X-Ray, unlike some of the way other performance tools are launched from Xcode, it remains running when you're done with the app. So we still have the previous run here, and I want to see other runs when I run again from Xcode. things I should have done and I forgot before I saved the template is to select the run buttons in each instrument. If I would have done that before I saved the template, they would have been selected now and I wouldn't have had to do that, but I'll just go ahead and do that now. Now I'm going to go back to Xcode and I'm going to say debug and I'm going to say launch using performance tool again and select the slideshow testing. It's going to open it up in the same trace document because everything about what Xcode wanted to launch was identical. So Xcode said launch this particular app in X-Ray and that's all it said to X-Ray and X-Ray said I've seen this exact request before, I'm going to keep the same trace document open that I have open that matched the last request. Now we'll go back to the app and it's running really smoothly. I guess our problem is solved. But as I said, X-Ray is really good at busting your assumptions.
This happens often where you came across some code you haven't seen before. You find a fix. You're in a hurry, and you move on. Well, in this case, maybe it wasn't the best of fixes because if I go back to X-Ray, I can see that the memory just kept growing. Even the really wacky, bad one run, the way we found the project with this terrible spiky curve, it eventually got rid of the memory it was loading in. But my solution isn't so great because it just keeps caching away each of those images and it never gets rid of them. So luckily I had that object-alloc instrument in my template. So I'm going to go back and undo what I did before.
And I'm going to see if there's a better way. Now, another great thing about these showing multiple runs is that that data is still there. So I don't need to undo the mistake that I made by using that really aggressive simple caching. and then rerun and gather the data again, I can actually just go back to X-Ray, I'll click on the previous run, and I'll look at the data again. So what else was going on in there? Let's use the flag navigator again to look at other things.
The other API it is showing me that has executed a lot is DrawRect. It doesn't do a lot here, but it does do a lot in DrawImage. I double-clicked on that. It took me somewhere else in that file, which is DrawImage. And I can look at this, and I can say, okay, well, what's it doing? Here's where it was making that fetchImage name call, So I'd cached that previously, but again, not a great solution. But it looks like if I would have had this underbar image filled out, then it would have just used that. And so I don't know. Let's find out more about that. And this is the part of the demo where, in order to save some time, I put in some extra code, which is, oh, this magical ability for it to cache the images itself. So we can pretend that that actually wasn't there. But in order to solve this problem, I can actually just cache the image in the viewer of the image. So I'll try that. I'll save it and I'll build it. And I'll go back to debug and launch my trace one more time.
launches the app, and we can see the animation is again smooth. Very nice. But we can also see that now I've arrived at the right solution. I've had my cake and I've eaten it too because it's fast and it's memory efficient. Probably without X-Ray I would have ended up with the fast but inefficient version until someone came along later and said, "Hey, your app is is not efficient at all." So let's go back to the slides, please.
So we saw in there building custom instruments. And again, I didn't want you to get overwhelmed by, gosh, I don't understand all these weird detrace-isms. I was using self and other things. DTrace is really cool and has a really great language. But it's a subject unto its own. So I encourage you to, A, attend the session tomorrow and read about it on the web and experiment with it in your leopard seed. But what I do want you to get is the general concepts of creating your own custom instruments. So one of the three pieces of critical information in the instrument builder was describing the instrument. This is going to represent the title, the tool tip, the icon, et cetera, that will be the instrument in the toolbox. So you really want something nice if you're going to reuse this instrument. The second thing was the conditions. Now, we had simple conditions there. We just said, when it enters or exits an API, do something else. But you can have pretty complex conditions that say, when it enters this API and I'm in this process or that process and this value is within these parameters, then do my actions. And then we saw the actions themselves and we saw two different types of actions. We saw the ability to record data back to X-ray, so we displayed it in the detail view and graphed it on the track view.
And we also saw some bookkeeping, so we saw keeping track of the number of bytes, looking at how much time is actually spent in an operation, all those sorts of things, you can do that with custom scripts for different actions. You can have multiple of those per probe firing.
So in summary, the preview of X-Ray, a new developer app, is in the Leopard Seed now. And you can use it today and even better tomorrow to tackle this problem of increasing complexity in our world as a software engineer, as a QA engineer, as an IT support person, administrator, et cetera. And you can use X-Ray to bridge gaps between developers, QA engineers, and IT support staff, Leverage DTrace to create your own instruments and create your own templates as custom tools to increase your own developer productivity.
So for more information, you can send an email to Matt Formica there. And you can also look on Sun's website for information on DTrace and just search the web. You'll find a lot of information on it. There's already a buzz about Apple having adopted DTrace, so that's really exciting. I'm glad that community is really excited for us, and we're excited to join them. And you can also, again, attend the session I mentioned earlier, which is in the OS Foundations track tomorrow. they're actually going to demonstrate using D-Trace on the kernel, which is really, really killer.