Mac • 45:40
Safari contains the best set of development tools ever included in a browser. Discover how to effectively use these tools to fine tune your website. Learn how to efficiently debug JavaScript, profile JavaScript performance, inspect and edit CSS, optimize page load time, and test pieces of code on the fly.
Speaker: Timothy Hatcher
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Tim: Hello everyone, I'm Tim Hatcher. Today we're going to talk about rapid development using Safari's integrated developer tools. But first let's see a show of hands, how many of you have used the tools that ship with Safari and some version of Safari. Great! That's a lot of you.
So how many of you have used tools in other browsers that you might be familiar with? Most of you too, that's great. So hopefully a lot of this will show you how to use our tools and get a good experience. But even if you haven't used our tools before, we have a great story to tell you today about using Safari's tools in the new version of Safari 4 that shipped this week, and how to take advantage of those tools to accelerate your workflow and get things done faster.
But first, whenever you're creating a website you're going to start using some tool, some creation tool. And it's probably a tool that you see, up on the screen. Maybe you've used Dashcode before to create your website. And they have a great experience in Dashcode that ships with Snow Leopard to create websites for desktop and mobile. Some of you might have even made one of these tools. I know a lot of Mac developers are here, and my favorite text editor up here is probably written by one of you out there.
But what are you going to do when you're done with these tools? You need to test in a web browser, and hopefully that's Safari. And what about when you run into some problems or need to develop and work a little bit in the browser, you need to change something? Well that's where Safari's great tools come in. And let's go ahead and get started and dive right in.
So the first thing I want to show you, if you haven't done it already, is how to enable these tools, then talk about prototyping and developing websites, and finding and fixing errors that creep into those websites, and then prototyping, or improving page performance. Sorry. So let's go ahead and talk about enabling the tools. Well it's really simple.
There's a check box right in Safari's advanced preferences where you can just turn that on, you get a new menu that shows up right next to the Window menu called the Develop menu. And all of our tools are right at home in that menu. So anything you have, your developer needs are right there in that menu. And that's it. That's how you enable the tools. So if you haven't done it already, go ahead and turn it on.
You might be able to follow along during our talk here. Now let's talk about prototyping and developing websites. This is the favorite part of the web development process, I think. Hopefully it's the same for you. And when you're developing a website, every website starts out with an idea, and hopefully it's an energy efficient idea. And that idea turns into a sketch or a concept that you start building and working on. And then a designer creates a final, nice presentation of that.
And the designer usually isn't the web developer, sometimes it is, if you're a designer and a web developer you're set. But usually the design gets handed off to you, and you're responsible for making this design come to life. And where I find it easy to tackle these problems, maybe the designer uses rounded corners and you've never dealt with rounded corners on the web before, or some transparency and opacity, there. Breaking these little pieces down and trying them out in little snippets can be really useful. And we have a great tool for that.
And it's the Snippet editor right there in the Develop menu. When you show it you have a window that has two panes. And these panes let you type in the content that you want to test, the markup or CSS or HTML in the top, and everything you type gets previewed below. So as you're typing you have live updates right below. Using the great WebKit engine, you can test out little snippets of code. And I find this really useful for testing those little pieces, trying out new syntax.
And once I take it to the next level and use my favorite content creation tool, like Dashcode, I want to then take that back into the browser. And how do I do that? And work back and forth between my text editor or my ID and my web browser? You 're constantly going to be reloading or testing out new CSS changes that you want to see what happens.
And you're probably going to be very familiar with this icon. You're going to be reloading your content all the time. But there's a better way to test out an experiment with CSS and DOM changes in particular. And I'm just going to dive right in to a demo and show you. So I have Safari 4 installed on this machine. I'm going to go ahead and open it. And I've already enabled the Develop menu, here it is right next to the window menu. So I've been working on this website, this blog that I've started working on.
And this is what it looks like. So I've been playing around with all these colors. There're all these vibrant colors. And I've messed something up. This header, it's supposed to be this purple color. And I really don't know why. So I'm going to go ahead and bring up the Web Inspector, a great tool for targeting and testing out ideas in the page, and experimenting and introspecting the content of this page.
So right in the Develop menu I'm going to bring up the Web Inspector. And the Web Inspector, by default, loads attached to the bottom of the window. So this Safari window now has a Web Inspector docked to the bottom of the window. And over here on the side, and the first panel is the elements panel, and anything in this is the DOM representation of the page.
And as I mouse around you'll see highlights show up on the page. And these are the elements and where they visually correspond in the page content. Well this header is something that's probably nested a few levels in the DOM, and I really don't want to go hunting and pecking through the DOM to find it.
And there's a great way to find things visually. And down in the bottom of the elements panel is this magnifying glass. And I'll just toggle it on. And what that does is let me search around in the document and see elements visually and find elements visually. And whenever I click it highlights that DOM node in the Web Inspector. So now I have my header that I'm looking for, highlighted in the Web Inspector. And over on the side anything that's selected in the DOM tree will show you the styles and other properties that show up for that element and apply to that element.
And you can see the background color is gray, and you can see a little color swatch here. And I'm really expecting that to be the purple color. So it looks like I'm missing some style class or something in my document. So let's find the element that's actually purple. And we'll use the Find tool again.
And it looks like that's getting its color from the new style class. So this selector is what is causing that color to be purple. And I can experiment using these text boxes next to the style properties. And disable those properties. So I can see what it's going to fall back to if that style never even applied to it at all. So sure enough it goes back to that gray color that I was trying to get rid of in my other header. And you can see things are now crossed out, so that style, that background color is not applying any more, and it's getting this gray color.
So I can go ahead and check that back on, so it's going to apply again. So it looks like it's getting the style class new from its parent element. And looking at my previous header the style was "hot", and I really want it to be "new" to get that purple color. So I can just simply double click to edit, and go ahead and type in "new", and I'll zoom back out and go to the top of the page.
[ applause ]
Tim: So sure enough, looking at the styles I now have another rule that's applying to these, this, this header. But this purple color really isn't pleasing to me. It's too vibrant for my taste. So just like the DOM, I can edit styles. Double click the Edit and I can type in any number I want, and just like before, and hit Commit. But there's a better way. If I double click to edit I can use the arrow keys to cycle through these colors, to cycle through the numbers.
And that effect applies right on the screen as I'm going through these colors. So I can adjust the individual color channels independently and find the color I'm looking for. So this is more appropriate for this page, this green. We can tweak this a little. And once I find the value I'm looking for I'll take it back to my original editor and apply it to the original page. So anyone that now goes to my site will see the new color. But they haven't been seeing any of these changes that I've been making.
They've been changed locally on this machine for this web browser. They're not applying to the web server, not applying to anyone that's visiting the site. So anything you change here is going to have to be manually taken over to your editor and applied to your site globally. And that's a great way to experiment without having any side effects. So that's it for the elements panels.
I'm going to go ahead and close this, and switch back to slides. So I talked about using the elements panel in the Web Inspector. And specifically the Inspect button to find visually any element that I was interested in on the page. And one thing I wanted to show you is the Search field. So let's go back to that demo and I'll bring up the Web Inspector again.
And say I'm curious now that I've gone back to my original content and want to know what's going to be affected when I actually change to the color of that header in the real source. So I can look and see, using the search field, how many headers I have on the page.
So it looks like I have 5 headers. But that's really not what I'm expecting, I want to narrow that down a little bit, because this one header is part of the top of my page, not these individual sections. So I can type in complex CSS expressions right here in the Web Inspector, so I can see all the sections that have a header under them. So now I just have 4 results instead of the 5.
So that's a great way to test out selectors that you might be interested in, see what they affect on your page just to go back to your original editor and add those new rules. So let's go back to the slides. So that's how to use the Search field to search for CSS selectors, tag names, or identifiers for ID elements. Then you can edit CSS Live and the DOM. With CSS you can use the check boxes to temporarily disable a certain property to see what the effect would be. And double click to simply edit values textually, or use the arrow keys to increment numeric values.
So that's a lot about CSS and the DOM, but what about JavaScript? I know a lot of you out there love JavaScript and are very familiar with JavaScript and finding elements. And you really want to know where is the command line for the web browser? And I'm here to tell you the command line for the web browser is built right into the Web Inspector. And to show you that I'm just going to jump right into a demo.
[ silence ]
Tim: So the first thing, and a good way to show you how this applies is I'm going to go to a website, and it's my favorite website in the world. Here it is, About:blank. It's completely empty document, but this is really useful to a web developer who might want to try out some things using the command line that I'm going to show you. It's a great way to start from nothing and build and come up with something that you might want to test and experiment with. So I'm going to go ahead and bring up the Web Inspector. And I'm going to bring up the console.
The console is the second icon in the bottom corner. And it slides right in from the bottom. No matter where I am in the Web Inspector I can always bring up the console. And I can switch around in the Web Inspector and my console stays right down there.
I can have a point of reference at the top for the DOM maybe I'm working on, and work on it with the console right below. So I'm not switching back and forth. And here it is, the command line, right here in the console. So I have this blank document and it's truly blank.
It's just got a head, and a body, and nothing's in it. And I want to try out something with the canvas canvas element. I've heard a lot of great thing about the canvas element in Darin's talk earlier this week. And the HTML 5 spec is building on the Apple invention of the canvas element, adding things like text drawing. And I'm working on this game with Kevin, and I want to draw some text in my canvas.
I have a whole bunch of stuff I'm drawing in my canvas, but text is one thing that I've never been able to do until now with HTML 5 using Safari 4. So I'm going to go ahead and make a canvas element, and I'm going to assign it to the canvas variable. And this is just JavaScript. I'm typing out live JavaScript expressions here.
So I need to create an element on the document. And as I start typing you'll see auto-completion kick in. So now it's found the document. And to accept that completion I can just hit the right arrow key. And that's the fastest I've ever typed a document. So I know document lets me create things.
So I can start typing out "create", and "create attribute" is not what I want, I want to create an element. Well, there's multiple creates, create the prefix functions on documents. And I can use the tab key to cycle through all the possible matches and "create element" is the one I want.
So I'm going to go ahead and create a canvas. And I'm going to hit Return to evaluate that. And the result is shown right below the expression. And since it's a DOM element it's going to show up in pseudo HTML syntax of what that element looks like. And it's a little boring, because canvas doesn't have any attributes applied to it right now. But that's all I need. But this, this canvas is not in my document yet. The body is still empty. So we need to append that to the document.
So I'm going to go ahead and append that, and
[ silence ]
Tim: Oops! It looks like I can't append to the document. Well, any errors that you run into will show up as the result of the expression. So you don't have to worry about creating a problem or having an error, it's just going to show you the error.
And I know, oh, I meant to type "body", and append it to the body. So now if you've noticed the body has a canvas element underneath it. And as I hover it it's showing up at the top and it's empty. We need to draw something into our canvas; "canvas" is empty by default.
So let's go back down and try getting the context. Any graphics context, like the canvas, you need to get the context used to call functions or draw methods on. So I'm going to assign the context to this CTX variable. And I'm just going to go a little quicker-"get context". And you can see how auto-complete really helps out with the typing. And evaluating that expression gives me an object, a JavaScript object I can interact with. Well I can expand that object and see all of the properties that are on that canvas context.
And the one I'm interested in is Fill Text. And that's the new one in HTML 5 that I've heard a lot about, and the font property. So let's go ahead set the font. And as I'm completing, you'll see auto-complete knows about this object that I'm working on, and it lets me complete to the font property.
So I can assign a font and it returns the result, and that's what I expect. And I'm also going to set the fill style, and let's just make that "red". And let's try out the fill text method and see what happens. So I know fill text by reading HTML 5 spec takes a string and it takes a location in the context, in the canvas. So I'm going to zoom out before I evaluate this.
And after I evaluate it you'll see the context now has some text. Now it's not that fancy. I know there's better ways to show text in a web browsers that's more accessible and things, but this is a good example if you need to draw text in your canvas you now have API's available in Safari 4 to do that.
So that's using the web instructor's interactive command line to be more playful with your JavaScript and explore a little bit and find things you might not have ever done before using the expandable objects. So let's go back to slides. So I showed you how to use the interactive command line in the console.
You use auto-complete to see expressions as you type them, so you know what you're typing, you know it's going to evaluate correctly. And I played with the expandable objects of the DOM tree, and my canvas element was a little bland, but if it actually had children I could expand that DOM element and see all of its descendants. And looked at properties of JavaScript objects that I can interact with. So that's using the JavaScript console to do experimentation.
Now the inevitable part. You have to find and fix bugs. It's not as fun as prototyping and developing, but you have to do it. It's going to happen. So hopefully what I show you is going to let you know how to use our tools to make this a better process.
So what are some categories of errors? Well there's markup errors and JavaScript errors. Well what exactly is a markup error? Well markup errors happen all the time and you might not even realize it, such as mis-nested tags. You have these tags closing in incorrect orders, or extra closing tags. And both of these are super hard to find just with code inspection.
You have to have a tool to help you with this, otherwise you're, you're close tags are 200 lines apart and you're never going to see that extra little P tag at the end. So those are really hard, and you definitely need tools to help. And improperly placed tags.
This might look like valid syntax, but a form is not allowed inside of a table, according to the HTML spec. So you wouldn't even know that unless you read all the specs. And those things are super thick, right? And then another one that bites people all the time, and it's bitten me a lot, until I started working on the Safari teams and it really got engrained in my head, is the self closing syntax in HTML. HTML is not XML.
Let me say that again, HTML is not XML. XHTML is XML, but you can't use the syntax in HTML. So let's dig in and look at this example. So I'm going to open up the Web Inspector again and look at the resources panel. And I see a bunch of errors. There's 3 errors that are caused on this pretty simple page.
And to see these errors, these are markup errors. And the markup errors are only going to show up if you load the page while the Web Inspector's open. We enter a special parsing mode that outputs log messages for you. Whenever it encounters a problem and tries to fix it. So this is really your window into what the web browser is doing, what the engine is doing to fix up your site as it encounters problems.
So you'll see the errors in the console. If you're more familiar with the console you can look in there for the errors, or you can look in the resources panel and see an error count on the side and all the errors in line. So you don't even have to go to the console. If the console scares you, you can just look at all your errors right in the context of your source code.
So let's look at the elements panel. And I know the errors are telling me that this anchor was cloned to 2 other locations, when I only expected it to be there once. So looking and verifying in the DOM I can see, oh, there it is 2 extra times. So it's simple to fix.
[ silence ]
Tim: Sorry about that. So I've reloaded the page after I've edited it in my favorite text editor. And you can see I've used the correct syntax, and I no longer get those 3 errors. And verifying in the DOM I can see I only have one of those anchors, I don't have 3 of them anymore. So that's just one example of how to use the Web Inspector to find problems that you might have been overlooking before, and target and fix those errors.
So now let's talk about JavaScript errors. So what's a JavaScript error? Well I ran into one in my demo and it was helpful in telling me what was wrong. But there's one that I always run into, and I don't know about you, but it's null undefined objects. How many of you ran into this error before? Yeah, it's that annoying. Well, hopefully our tool is going to help you find and fix those. And I've got a great example that hopefully Kevin can fix for me.
And there's sometimes you're using a JavaScript library that has explicit exceptions, and it might be throwing, maybe you're passing an incorrect argument to one of its functions. And then there's parse errors. You misquote a text string and the world blows up. So let's jump right into the demo. And like I said, hopefully Kevin can fix this game that I've been working on. It, I totally broke it before this session. So hopefully he can use our tools to figure out what the problem was.
Kevin: Oh, thank you Tim. Let me switch you over to the demo machine, and let's load Tim's site. I personally don't like the Web Inspector docked, so I'm going to use the icon on the bottom left here to pop it out into its own window and I'll use it from up there from now on.
Tim's game is this link here. And sure looks like it's not working. We can already see that in the bottom right corner we've got an error badge, so I'm going to zoom in on this. And if I click on this badge it brings up the console and it tells me what the error is, "current cell is undefined." It also tells me the line number and file name, so I can just click on that and it's going to open the file. Just looking at it, it's not immediately apparent to me what's going on. So what I'm going to do is I'm going to turn on our JavaScript debugger and see if we can find this error better there.
So the debugger is this Scripts panel right here. And because we want to give you as much speed as possible in our new nitro engine, the debugging hooks are not compiled in by default. So you just have to turn them on yourself. And I know that an exception is being thrown. And in the bottom left corner here we have a button that will pause the debugger when it encounters an exception. So I'm just going to turn that on, and then I'm going to reload this page.
[ silence ]
Kevin: All right, so I've hit my exception. And we can see on the far right here that current cell is indeed undefined. I can also use the console and it's contextual to wherever we are in the JavaScript stack. So I will just type current cell, it is undefined. The line above I see it's being assigned cells that cell index. So let's just see what cell is, or cells That's an array of objects. That looks correct.
And
[ silence ]
Kevin: "Cells that cell index" is undefined. Cell index, 198. I can also see that over here "cell index is 198." And in this for loop [phonetic] we're going until the cell's length. So what is the array cells length? It's also 198. I've run off the end of my array, or rather Tim has. We can see that in this for loop we're using <= instead of just <.
[ silence ]
Kevin: Here's our JavaScript file, I'll make it a little bigger. Once nice thing about the Inspector is I can see that that for loop is on line 152, so I can just go straight to it. Here's our less than or equal to. And I'll do that. I'll save. And then we'll reload this page.
[ silence ]
Tim: But wait, I don't think that's supposed to be gray. Maybe it's supposed to be another color. I don't remember having any players be gray. Maybe it's the fill style, I might have messed that up.
Kevin: All right, we're doing some more work for Tim here. So he says to check fill style, so I'll just search for it. Fill style, it says we have 4 matches, and our first match is being assigned the army color. We'll just set a break point there, got a hit immediately. And on the right we can see there's the army object, and if I expand I can see the color.
Oh, I've already found a gray army. Looking at this object I can also see there's another color where it's defined purple, that's probably what he meant. Looks like he spelled colour with a u. So let's go back to Dashcode and we'll just look up color. And there we have it. We'll save this. Reload our game. And we're purple.
[ applause ]
Tim: Thanks Kevin, now I can play that when we're done here. My British tendencies in spelling color wrong. So Kevin showed you how to enable debugging in the scripts panel of the Web Inspector. And using the Pause on Exceptions button to always pause whenever an exception is hit while debugging is enabled.
So that's super useful so you can catch those errors right when they happen instead of seeing it log out in the console, and wondering, and scratching your head, oh, who was calling that, or why was that happening? And how to set explicit break points. If you have code of interest so you can target specific parts of your code with a breakpoint.
And then Kevin used the Scope variables on the side, to expand one of the objects to dig deeper, to see and find my misspelling. So that's how to debug and find and fix JavaScript errors. So now our sites working great and we really need to think about performance. And there's some areas of performance that you should focus on. And performance really comes down to resource loading and then JavaScript.
So let's talk about resource loading. But first think about this all in the context of Desktop and then all the iPhone users that are visiting your site. Even if you haven't optimized and created an iPhone version of your site, more and more iPhone users, even you guys, are visiting normal sites. And you want those sites to load as quick as possible. So, let's talk about how to improve resource loading so those pages load snappy on the phone.
So there's a couple categories of resource loading issues that all affect page load performance. So first large resources. And this is pretty obvious, but let's talk about how to find them in the Web Inspector. So I'm going to open up the Resources panel and I'm going to sort by size using the size graph. And this will bubble up all of the larger resources that occurred during the page load of this site.
And also at the top here is a great summary of all of the resource categories types, like images and scripts, of how much they take up. And you can see by the huge amount of orange here that JavaScript is really the culprit in size of this site. And sure enough that was a very easy way to use the Web Inspector to find larger resources, and maybe you can eliminate those large resources by reducing those scripts, getting rid of functions that you don't use, using server side gzip compression. So now let's talk about large in number of resources.
And we can go to the Web Inspector's resources panel again and sort by time, using the time graph. And you'll see a nice waterfall of where and when these resources were loaded. And you'll see two different colors of these bars. The first part of the bar is the latency, how long it took from when the web browser needed that resource, to when the first byte of that resource was received from the server.
And then the dark part of the bar is how long it took from the first byte to finish downloading the resource. So you can see right away there's some high latency here. And remember, we're, we're targeting the large numbers of resources. But I'm talking about latency for a reason.
So let's sort by latency here. This will re-sort the time graph. And for those that have good eyes you'll, you'll notice it took me 12 seconds to load Apple.com here. That's pretty slow. Well I was testing out iPhone 3's tethering, which hopefully you guys will be able to take advantage of soon.
And you'll see this first resource here what took 2-point-something seconds before anything was gotten from the web server. So the web browser needed it, and then 2 seconds later we got something from the server using the cell network with tethering. And it took 12 seconds total to load the page.
Compare that to a cable modem where it only took 1-1/2 seconds to load the page. Even though the, the latency bars look really large there, it was only 315 milliseconds of latency. So no latency really should be ignored, even those 350 milli, 15 millisecond latency. But you really can't do anything about the latency problem. You can't go and up grade everyone's Internet connect and fix all those problems. Well, the way to fix that is large numbers of resources.
And remember that's what we were talking about. So I'm going to go back to the size graph and scroll down the page, and you'll see at the very bottom, remember scripts was a large part of this page, so we should really focus on scripts. But it turns out there's 6 teeny little scripts that are loading on this page.
And anything I could do to reduce this, knock it down to 1 script resource that I need to load, would greatly improve the latency from 6 different pieces of latency to 1 piece of latency. So that's a way to target large numbers of resources and improve the latency problem and speed up page load. So now let's talk about serially loaded resources. And this is somewhat hard to digest. But an easy way to find them is open up the resources panel, sort by time again, and sort by response time.
So now everything will be sorted by the time it got that first byte of data from the server. And then I'm going to scroll down. And I noticed that there's these 2 resources that are coming from a different domain, and you can see the domain underneath the file name here.
And those resources look like they're causing, the first one is causing the second resource to load. So that's really pushing out the page load time, because that first resource says, oh, I need these other resources, go load these for me before I can finish the page load. So reducing any of that or putting them earlier in the page load would greatly help the total time needed to load your page. So that's 3 different ways to find resource load problems and fix them or identify them using the Web Inspector. So that's resource loading. Now let's talk about JavaScript performance problems.
And when Kevin was fixing my game I noticed there was a change I made, also, that seemed to have slowed down the artificial intelligence of the game. So hopefully Kevin can come back up and use the Web Inspector to see how I'm doing in our artificial intelligence performance.
Thanks Kevin.
[ silence ]
Kevin: Thanks again Tim. So, have the same game up. I've actually instrumented some of the code, but I commented it out to show the time that things are taking. So let's go to the top of our JavaScript file. And you can see that I've commented out a couple of lines of code here, 2 at the top of this function and 2 at the bottom. This function is called once every time the game moves all of the artificial players. And what I've done is I've used our console.log function, which is just like Print F Debugging.
It'll just spew a line of text into the console, in the Web Inspector, and I have created a couple of objects. And in the second use of console.log you can see that I subtract the end time from the start time, so you can actually just embed objects and things into the log messages. So I'm going to save this file and reload our game.
And now in the inspector what we should see is these messages showing up-let's zoom in there-every time the computer makes a move. And we can see the times are varying, there's 7 milliseconds, 14 milliseconds. The game randomly picks which players get to move that turn. And so there's not a lot of consistency here.
So even if I sped up this function it'd be hard for me to determine if it had done any good, maybe I could take out the randomness and try to stabilize it a little bit. But we have a better tool. We, this is a personal favorite of mine, we have up here the Profiles panel, and we have a JavaScript profiler. Just like the script debugger, you have to enable it to add the profiling hooks. But right now it doesn't have anything to give it any information, so we're going to turn that on.
Then go back to the code and instead of using console.log, I'm just going to change this to "console.profile". And I'm going to give this a different name. You can give a profile any name, or you can leave a name off. If you do give it a name, however, then when you call "console.profile" end, if you give it the same name then it will only shut down a profile of that name. If you have multiple profiles running and you call "console.profile", and it'll just close whatever the last one that was started.
So I'm going to save that, reload our game. Now we should start seeing some profiles show up. Because I have named all these the same thing, what you'll notice is that they're starting to be enumerated with run 2, run 3, run 4. And when I look at a profile I can see all of them showing up underneath.
So this is a way that you can compare successive runs of the same profile information against each other to see how they vary. One thing I'm noticing here is that the function Draw Cells is often the first or second function here. I also see stroke. And if I expand that this, currently we're in the heavy-up view, which if you're used to Sharks, this is I think it's the default. And so if I expand one of these it's going to show me who calls these functions.
Stroke was called by Draw Cells, and run, one of these I saw Anonymous function that was also called by Draw Cells. So I'm starting to think Draw Cells is my problem here. I see this being called 17 times and it's taking about 3 milliseconds in this case. Well I just so happen to know that in Tim's game, originally, he only intended all the cells to be drawn once every time AI makes a decision. So yeah, it would move all the pieces and then redraw.
So it shouldn't be being called 17 times. And if we look at the code we can see that there's a call to draw cells here that is inside the for loop. And that's getting called every time the for loop runs instead of just once for the whole function. So I'm going to move it to the bottom of the function.
[ silence ]
Kevin: Here we have our profile information again and we can see Draw Cells only had 1 call. And it took less than 2 milliseconds. So that's the way to use the profiler to find information about the performance of your JavaScript. Turn it back over to Tim.
[ applause ]
Tim: Thanks Kevin, now I can really play that game a lot faster than I was able to before. So Kevin showed you how to enable profile line hooks in the profiles panel of the Web Inspector. And using the console.profile, and profile end functions to target specific pieces or your code that you might want to verify-remember test, but verify, or trust but verify-and that will let you target specific chunks of your code so you can know that you really sped it up or you really messed it up and slowed it down. And then grouping of multiple profile runs.
And that's really useful for comparing multiple uses of that function to see how things are affected by randomness, as was the case of this game. So that's pretty much it. I showed you how to enable Safari's developer tools. And hopefully you've evolved on that if you're interested in developing at all using Safari. And I've talked about using the tools to prototype and develop sites, and how they fit into the whole development process.
And then using our tools to find and fix any errors that you might run into. So using the JavaScript debugger, or using Print F Debugging in the console. And then improving page performance. Really improving your websites page load performance for, not just your desktop users, but your mobile iPhone and iPod touch users.
And using the JavaScript profiling to really verify your code changes are fast as you think they are. Even though our nitro JavaScript engine is blazingly fast, 20 times fast in Snow Leopard than it was in Safari 3, you really need to improve your code stump. So for more information there's Vicki Murley, who's our Safari Technologies Evangelist, and there's Mark Malone, the Internet and iPhone Technologies Evangelist.