WWDC2003 Session 416

Transcript

Kind: captions Language: en I'd like to welcome you to session for 16 today we're going to be talking about performance in your carbon application I suppose everybody has been seeing like you know what we've been doing with the g5 you probably went down to the lab so the performance a bread machine you've got petitions are going to get a boost in performance you probably all very happy about that it's very cool now you probably the chance to it start Panther and run your application as well you probably notice the text we do a lot of operations are very fast in painter because our engineers spend a lot of psycho sort of resources and time to make sure that operations of very fast in tender we talked a little bit you know we discuss on monday in the in the mac OS temptation the State of the Union about things such as text drawing being twice as fast all of this is great but when our customers are going to buy the next g502 gig earth is the launch your application and they get the spinning krypter of death that's not good but doesn't do us any good to have like the best meshing on the planet to have the best operating system if when somebody gets like in or third-party applications that performance so that is not there and this is really the goal of this session what we're going to be talking about that we're going to be talking about how you guys can take your application to the next level we're going to talk about tools because now we have actually very good tools for to enable you find out what other performance issue in you up we're going to talk about technologies that can help you improve the performance in your application and we're going to talk about two different kinds of performance today we're going to talk about the real performance which is you know how long does it take to process an image which is like you know 500 megabytes how long does it take to learn the future how long does it take to access the web to download the URL to access the database but we talked as well of what we could perceive performance which is what happens when a Persian execute do you give feedback to your user or desvelo the application look you know cannot hang and if there is one thing I want you guys to realize and to understand with this station is that now I think Apple have shown you that we spend a lot of cycle and resources and we have an OS that is very fast Mac os10 is we're both mature and you're going to see with the hardware we've done an excellent job in looking at what we were doing wrong in performance now I think it's up to you guys to go back to your room to go back to your feces and start using sharks they're using sampler moving to Mac oh and use the latest technologies that we have in the toolbox in networking in filet o to really get the best of Mac OS them and for that I like to invite Kurt Kurt is going to be talking about all this topic and ask you for a tunic thank you put your logo Thank You Ravi a so like eggs a VA mentioned performance is critical to your application if your app doesn't perform well users are going to make judgments about the quality and the polish of your app and a Mac os10 as a system so while we've been optimizing parts of the toolbox and of carbon we've identified some techniques to identify where there's performance problem areas and we'd like to share those with you we've also identified some techniques for improving those areas once you've identified what those problems are we'll show those with you as well and also talk about new technologies in Panther and also to reacquaint you with some technologies which will give you the best performance on Mac OS 10 so there's four problem areas i'm going to talk about today and that's application launch it takes a long time for your app to come up and start processing event the user is going to feel as if the system is sluggish we'll talk about low level services and that could be with your use of memory api's how you're allocating memory also with file network i/o and threading drawing now this is huge this is a huge aspect of your application it if the user clicks on a background window and it takes a long time for that winner to come up and draw its context content the user is definitely going to get the impression that your app is sluggish or maybe the system's not performing very well and finally we'll talk about poor responsiveness let's get right into talking about application launch performance so in identifying what you can do to improve the performance of your app it's good to figure out what's going on during launch well there's a lot of file i/o the second the user clicks on your icon or double clicks on your icon this system starts loading in the executable for your app the associated resources you're probably loading and preferences may be registering and initializing plugins and on top of all the file i/o the system or your app is doing its standard initialization that's going through and allocating large chunks of memory maybe doing some table initializations and etc so how do you find some of these problems well during launch to identify problems with with how you're utilizing the CPU launched it with a sampler and samplers the utility that sound in developer applications and by launching it from the UI what sampler does really is it takes a periodic snapshot of where your app is dirt in the execution so when you're done sampling it it compiles us all together and you get a list of where most of the time is spent is your app app and so you can identify areas that you can focus on and optimize now in terms of the file i/o what's going on you can use the command line utility FS usage and this will allow you to identify what areas are being where what file i/o is happening on behalf of you by the system loading and resources and whatnot and you can identify maybe you're loading its files that you didn't expect to like document templates or images that could definitely be referred to a later time so some solutions for this all those areas that we talked about all the file i/o and all the initialization that's going on you can you have some control over now internally we compile our frameworks with the optimization for size and we recommend that you do that too so this will make the binary smaller the system has to load less in and you can do this you in Xcode there's a preference for optimization level you can use optimized for size and you can also do that using other compilers as well what's really important is to always provide feedback to the user if it's going to take a really long time for your app to launch it's a good idea to put up a splash screen let them know immediately that your app has been loaded and things are going on even better than putting up a splash news to provide some type of progress within that splash screen let them know that some components are being initialized new plugins are being registered and the best solution of all is that put up your main document window as fast as possible this gives the user the impression it's perception that everything's up and running even if the foundation and other parts of your app aren't really initializing ready to go if you can get that document up as fast as possible it gives them the impression that you're ready to go you should also avoid IO during launch there's a lot like I said Systems doing on your behalf if you can avoid reading in document templates or some preferences that can be deferred to a later time that's excellent and you should always avoid writing during launch launch is considered a read-only process your reading in parts of your application getting ready to go you shouldn't write and then also take advantage of lazy initialization techniques and I'll talk about what that means in a second but it's a technique that allows you to defer allocation and initialization of components to later time and closely coupled with this is to avoid static class construction if your C++ base and you have a static class defined in one of your modules and what I mean by that is a global it says static foo and then the instance keep in mind that that instances constructor is going to be in soaked before main has ever called so before you can even start processing events there may be a lot of code that's being executed I mentioned a lazy initialization what does that really mean well rather than initializing component in anticipation is going to be used just defer that until later time until a couple is actually going to be executed and it's really as simple as defining a static boolean indicating that that's initialized to false to indicate that your component hasn't been initialized yet and later on during the execution of your app when before that component is used check that flag if it hasn't been initialized go ahead initialize it and then toggle the flag now the reason lazy initialization is a good technique on macros 10 and was maybe not a good technique on classic Mac OS and what I mean by that is Mac OS 9 and earlier is because maccalister 9 had really tight memory constraints and you had to deal with the problem of memory fragmentation so it was a good practice on Mac OS 9 and earlier to allocate as much as you needed up front but you knew that you were going to be needing so if that were to fail you could bail out as soon as possible rather than letting the user make a document that it may be a destructive operation later on when you needed this memory but on that goes 10 there's a lot more memory there's a huge virtual address space you don't need to worry about that you should always cook defensively still but be aware that lazy initialization is a good technique to group performance of launch now next we'd like to talk about the low level services such as threading memory and network and file i/o and to do that I'd like to bring up the manager of the core services team John orochi thanks Kurt so threading memory and file what do these guys have in common one of the things they have in common is that they're often not very apparent in when you're looking at your application in terms of contributing to a performance problem but the benefit in looking at problems performance problems in these areas is immense you can get a lot of time back by looking into these three general areas I'm going to go through these areas both suggesting what api's to use for these technologies and also some tips in the areas in terms of figuring out what performance problems you have in this so starting with Freddy first of all if any of you haven't heard the message so far that cooperative spread manager the carbon Fred manager is really not a it was supported for compatibility with OS 9 supported for the carbon transition it's not a great solution for threading on Mac OS X primarily the biggest flaw there is that in order to get your threads scheduled you have to call yield yield any thread and that doesn't really work well with a blocking model we'd like you to block on event in the run or run loop or event loop and if you have to be calling yield to get your threads to run those don't work very well together and unfortunately we can't really make too many changes in that that thread manager because of the expected behavior that that your apps have the good news is there's two solutions to general solutions for what you're using cooperative threads for dj's one is to use carbon event timers for periodic thing this is a great solution for it you have to update something occasionally in your UI and if if you have a different kind of problem usually that will lend itself well to preemptive threads either in the MP threading API or the P threading API and sometimes you can use both in combination mp3 s and P threads are both fully supported OS 10 api's there are some slight differences but they're very similar it's mostly a your choice on which API is to use it's mostly going to be dictated by the codebase that you have the thing to remember with threading in general is don't just because it's a pre-emptive operating system don't assume threads are free they're backed by Colonel resources so use them well make sure that you're making that you're just making good use of these threads a lot of times because they're available because they're kind of a nice construct to use it's convenient sometimes threads will be overused and that will contribute to your performance problems sometimes in a way which it's kind of hard to find and I'm going to go into that in the next slide one good guideline that I'd offer you is think about the work that you're actually going to do on that thread because remember you have to create the thread at some point and you have to message over in some way to the threat to get it to do work and oftentimes even if you create the thread and pass it some parameters you have to still wait for the thread to complete and then message back to your main thread so there are costs involved just in using threads not to mention you typically have to lock and you're using threads and there's a cost there too okay in the tip area for threading first of all if you're not already familiar with it in gdb there's there some support for debugging threaded applications the thread apply all directive lets you do various gdb commands the obvious one that most people know is try to apply all stack crawler back-trace so you can see where all the different threads are and Panther there were some changes so that the ID that's reported in gdb actually maps to your underlying mock drags it can actually if you can't tell from the stack crawl or if you don't have symbols for whatever reason you can track it that way the other tool to be familiar with its top it'll tell you at least how many threads you're using this is good because you can actually see if you're you have threads coming and going how many threads you're getting it at kind of a high-water mark how many threads you typically have and then look at those threads and see do you expect them to stay you know beyond the duration of a certain operation sometimes people just leave the thread sitting there they're not doing anything there's kind of a trade-off but you have to decide in your app if it makes more sense to get rid of that thread or not there are colonel resources associated with it so if you're done with it you might want to just clean that up and then lastly I'd really encourage you to look at the thread viewer app it's the best tool on a system for actually visualizing what's going on with the thread it lets you look on a per thread basis how you're using memory what kind of locking is that you have and thread priority okay after threading I would really encourage you to take a look at how you're using memories AP is particularly the carbon memory manager first thing I'd like to say is that we when we look at all of these api's at the carbon transition we actually looked at some of these and said do we really really need them because there's some issues there h lock and IH unlock unfortunately we're fell in the category if they had to be there they had to be there so you can your app would continue to work on nine so in order to enable a binary that worked on both nine and ten we had to support each lock in each unlock there's really no good reason to have them on 10 and there's a certain performance problem with frequent use of h lock and unlock especially they're doing nothing of use for your app so take a look at how you're using H lock and unlock a lot of apps internally we've looked and seeing we don't we don't bother we you continue to use it and we don't really need to use it the only time that a handle is going to be changed kind of out from under you if you will is when somebody explicitly called sit to handle sighs so look and see if you're doing that yourself or look and see if you're relying on the side effect calling H lock and unlock and then in general memory and free are the api's that you should be using for your everyday usage the memory manager is another layer on top of these so it's not going to help having that layer when you're really talking about performance sensitive code and memory and free or what you want to be using when you use our debugging and development tools if you have seen sampler on the Panther seed you've noticed that there's there's new support and sampler it's really been revamped will let you visualize some of some of your memory usage patterns and particular tracing capabilities are there which is fantastic we've done a lot of performance enhancements and Panther based on this technology being able to look and see how often were allocating and what kind of allocation patterns we have you can also look you sampler directly to look for your use of H lock and H unlock and set and get state and then of course Malik debug and the leaks command line tool that's both for the performance of your app and the performance of the system in general and I get in the habit myself of just using top over and a side window top down w so it shows you Delta's so you can see if you have a leak or if you're growing larger than you would expect to be growing during this particular operation okay so threading in memory is one area where you can you can really improve your performance by looking at it with those tools files is another files is one where I really recommend that you get involved with the tools particularly FF usage but let me start with the api's first of all FS rest api is what you want to be using at this point if you haven't heard that message please please please go back and look at your ear used to do file manager you don't want to be using FS back based API is the older flavor of the file manager aside from the Unicode problem there's a bunch of performance problems associated with the old AP is OS 10 is a Unicode system from the ground up and you want to be using these api's in particular like to draw your attention to two of the api's that you may or may not have heard of the catalog info and get volume info api's are tuned for 10 they let you actually ask for only where they let you be very specific in what you ask for so if you just need the name of a file and nothing else you can actually express that via the eff get catalog info or same thing for volume or maybe you just need the v ref num order ID of a file or volume this particularly pays off over network volumes and over non HFS like volumes and POSIX volumes so you'll see the benefit of using these api's on those kind of volumes and I really encourage you to test your applications on these volumes you'll see different characteristics it'll tend to exaggerate your file iOS and you'll see that it does impact your performance in general we take the stamps we've taken internally at Apple is to make sure that we reduce the total number of ions every single IO eliminated is that more that much more time you can devote to other things and on a network every single IO particularly on the flaky network is a potential stall for your app so consider that tips in for files I think we've already heard about ffs usage particular I would encourage you use the dash W which I don't have the on a slide here which shows you a little bit extra information on a wider terminal screen it shows you errors and it sizes and addresses of your buffers things like that and the dash f flag is new to Panther it lets you isolate file system versus network I oh you can actually use zephyrus usage for networking I oh and then this is actually in the man page for BYOD but do you while the image suffix is how to enable file manager specific tracing and if you enable this in your environment then run your app in the terminal at the command line you get not only the low-level POSIX calls in your trace but also file manager call so you can actually map them that way you can see that oh this particular use of FS get cat info caused us to do an L staff or an open and a closed or something like that and then in terms of how to best use the api's make sure you use large page line buffers that's still a very good thing to do and when you know you don't want the data you're just trying to write something out to disk you already have something in memory you're not going to go back and reread it from disk use that no cash pit that'll stop us from buffering it for you okay in there you have networking GF network which has a pretty in depth talk at friday at five is our first answer for you for most of your networking needs see if networking is designed to be very high-performing it's designed to work very well as an asynchronous API with the run loop see efron loop or the carbon event loop and there again the guidelines are to use large buffers so that you avoid going in and out of the colonel on your iOS and if you really really care about optimizing performance particularly over varying different link speeds you probably want to look at using adaptive solution so look at the size of your buffer see how much you read and write maybe start with something conservative double it up until you get to a point where you think you're getting a map throughput this isn't particular important over slower speeds slower speed links like modems and then on the don't use category of networking api's open transport is another one of those api's which we brought to OS 10 to help you bring your apps over it is not optimal open transport by itself has several threads and its implementation and it's there for compatibility we're not extending it so the two really replacements is either sockets if you really need that level of functionality or CF network and then if you're probably if you're at a higher level and using URL taxes there's two solutions there to see if network if you really care about some of the details of the protocol that you're dealing with so HTTP or ftp or the new AP is and web foundation nsurl request and if URL response and then again you can use FS usage for measuring network and be surprised just leaving FS usage running on the terminal and just using your app lets you see how you're using the network and then the best tool if you're really particularly if you're interested in what's happening at the protocol level is TCP dump that's the best tool that we offer to let you actually examine the packets in detail ok and I'm going to turn that back over to Kurt to talk to you about drawing performance [Applause] thanks John so next we'll talk about drawing now like I mentioned this is a huge issue if you're not drawing as quickly as possible and this is in terms of the the amount of bit of your drawing or the efficiency of your drawing the user is definitely going to feel a sense of sluggishness so there's three problems that I'm going to talk about in terms of drawing performance and that's too much drawing inefficient drawing and then there's the text performance aspect of drawing let's talk about too much drawing that can be broken down into problems of scope and frequency and that means that in terms of scope let's say that you need to update one controlling and rather than updating that one controls visual state you're updating the user painted it that contains it or maybe the entire contents of a window and then in terms of frequency may be that you brought your drawing periodically your drawing too much based on like a timer or maybe you have a real time based system that's that's pulling in some information for display but the users disable that so there's no sense in updating that and that consumes resources from other apps and utilities running on your system and generally slows down performance so how do you identify whether you're drawing too much well an excellent utility is to use quartz debug now this is in developer applications and this will allow you to identify problems both in terms of scope and frequency and it works with all carbon drawing whether you're drawing with quick draw or quartz and to find problems in terms of scope you would check the checkbox for flash screen updates and yellow and what this does is every time something is drawn or flush the screen it will show you the or it'll flash and yellow that area that's being drawn to the screen so you can visually identify what areas are being drawn too much if you just need to be drawing one controlling your drawing the whole contents of the window you'll be able to identify that visually now in terms of frequency you can check the checkbox for flashing identical updates in red and this will slash parts of your UI with red every time the bits aren't changing but you're flushing the content so it'll help you identify where where you're drawing too much in these areas don't need to be flushed so once you've identified where you're drawing how do you resolve this well just this is really up to you you need to identify what it is you need to be drawing when you need to do it and you need to go through your own code and figure out these areas for optimization now of course we have technologies that we'd like you to take advantage of which will help in that and i totally recommend adopting a chive you the reason for this and this is for your custom content and this is also known as compositing mode and the reason i encourage you to adopt is because it is designed specifically to draw as little as possible it's based its architect is around an invalidation model which is superior to the drawing model because when multiple areas of your view need to change you invalidate those areas and then the view system will come down and call your main draw a bottleneck so you'd only be drawing when the system is telling you to so this encourages the use if you need to update multiple parts or many parts of your app or your view all at once there will only be one net draw operation it also allows you to specify opacity and this is important because any view system is a hierarchy and that your view may need to be drawn after the views behind it like if it's embedded in a user pain which is also embedded in the window if there's any type of transparency with your view all these views behind need to be drawn first well HIV you can optimize this if you indicate to it that you are opaque your viewers opaque or maybe part of your view is opaque and the new system can optimize by not drawing the contents behind your view and encourage you to go see session for 25h I've you and depth this will give you more information about a chive you okay well my content not in a chive you is not drawing a composite window what can i do then well keep in mind that every time you change the state of your controls or a value of your control that controls going to need to redraw in a non composite window for example a scrollbar when you assess the minimum the maximum and the value of that scroll bar it's going to be drawing three times another good example is the pop-up button control when you add items to that control each time you do that it's going to redraw so if you need to do any type of bulk of value operations in a non composite window hi dekh control do these bulk operations and then show that control so rather than having a draw count of n for that many of operations you're going to do you'll have a net draw count of one also you can mimic a chive you like behavior by paying attention to update regions so don't draw things that are already valid so you can pay attention to update regions if you're paying attention to update event or you can mimic behavior by using the window the valid window wrecked or valid window region API the next area of drawing problems performance problems is inefficient drawing now this may be because you're doing too much work to get the bits you need onto the screen and that could be because you're using the wrong api's or using api's inefficiently or maybe there's some better alternatives on Panther to do your drawing so again how do you identify that you're doing your drawing and efficiently well the best technique is to sample your drawing code like I mentioned before it's going to take periodic snap snap shots of your app is so you can identify where most of your time is being spent and where you can optimize that also visually go through your code inspect what's going on within your draw path see where you can optimize areas out and here's some stuff you can look for triple buffering or multiple buffering now again on classic mac OS mac OS 9 and earlier you're dealing with constrained really tight memory and it was generally easier and more efficient to redraw the contents of the window than it was to keep those bits around well Mac os10 obviously has a double buffering system so so that it takes care of tearing and flickr for you so again like on a classic system if if you wanted to avoid this type of tearing or flickr you would instead employ double buffering techniques which is to draw into an off-screen and then copy the contents of that offspring all at once so if you're maintaining code that was originally written for a macro steiner earlier or targeted for those platforms keep this in mind that if you have application level double buffering this is completely unnecessary on mac OS 10 just in innocence to avoid flickr and pairing also inspect your your drawing code and see if region processing is showing up in our samples if you have complex regions this can be kind of expensive now I should point out that on Panther that the internal implementation of regions has changed so it has better performance and there's no 64k limit anymore but if these are showing up in your samples it might be a good idea or is actually a good idea to use simpler regions like rectangular regions is a good example if dirty region maintenance shows up your samples and this is because let me decide to fight it why that is is it quick draw each time you do a draw operation it needs to maintain this dirty region that is going to flush the screen later so if you're doing a lot of quick draw operations maybe this dirty region maintenance give a show up so if you know ahead of time that you're going to be doing a lot of operations into a particular region you can you can tell quick draw ahead of time using the API QD set dirty region then perform all your drawing operations and it completely removes the overhead of quick draw dealing with that dirty region for you now this is another important area like I mentioned on classic Mac OS it's easier to regenerate information or it's more efficient to regenerate information that it is to keep this information around well redundant calculations may show up in your drawing code and a good example of this is when we were optimizing the tabs controller we're looking through that and if you think of a tab the task control to user pain they've got the tab items with it with text drawing in there and each time we would go draw we were getting the text dimensions for each of those items figuring out the metrics of each item and then going through with the draw operation well the metrics of the texts and the labels they're not going to be changing that often so it doesn't make sense to recalculate that each time it's a better idea to cast that information so go ahead and cash to avoid this problem you may be mixing quick-draw and corks drawing now this can be inefficient because the quick-draw port is not synchronized for you with the courts con texted back that so avoid this type of drawing so for example if you're going to be using appearance manager api's for your drawing which you should avoid and I'll mention that in a moment but there needs to be some synchronization that that's behind your back to keep that quick-draw port in the CG context in sync if you must mix this type of dry and quick draw in courts drawing do it in block for each framework to avoid extra overhead so draw with all of your quick dry api's first followed by all your courts drawing or vice versa so on the front of using new API using more modern a prea api's we recommend using course I mean for all of your primitive drawing you should be using courts so this requires you to generate your information courts native formats and you can use do this at Build time so if you can convert all of the information to courts native formats like PDF at Build time that's good and you can also do this at runtime for example there's the quick-draw API to convert or to draw picked into a context so at runtime you can take a pic you can draw that into a context associated with the PDF context and use that cash that information and then use that image for subsequent drawing so you're probably thinking well Kurt you're telling me to draw with corks but I'm all my drawing code is based on quick-draw how do I do this well to get a CG context from this quick draw sport you'd use these api QT begins CG context and cue the ncg context and now what this does is it will cache that context for you so you don't have to so this allows you to print with both CG and quick draw drawing on the same page but you should keep in mind that in between these api's quick draw drawing is going to be disabled now also you shouldn't use the API QD begin CG context draw using some courts and then in that context and then repeat that over and over you should consolidate all of your course drawing between these api's also keep in mind that the CG context and the graph port aren't synchronized so if you need to synchronize the origin or the clipping region you'll have to do that on your own so what's the difference between a flush and the synchronize quite simply if you do cg context flush it tells the the draw system that that that context is going to be flushed at the next opportunity it can be so it's generally an immediate response and CG context synchronizes for Adelaide flush so this is more like queuing up different context to be flushed context so hot to see so so what you would generally be doing is doing all of your drawing and then call the api CG context synchronized to let the draw system know that that's going to need to be flushed and then the H I tool box during its draw loop will flush the context for you other api's you should be using are the new HIPAA p is now these are new and Panther and it's a simple mapping between the old appearance manager API and these new API so for example if you're drawing some steam primitive like using the API dropping button there's no coolant API called H I theme draw button so I encourage you to check out HIC hm and the reason these api's are now available is because when you're using because we're doing all of our drawing the toolbox is doing all of its drawing with corks natively so if you're drawing with the quick-draw api's the toolbox needs to either create a context for your port or use a cash for it and deal with the maintenance of that so by exposing these api's you're in charge of the context it requires you to create a context to maintain that context for your drawing and all of these api's require an orientation this is because the high-level toolbox and quick-draw deal with a top left origin based view system and quartz due to its PDF background deals with the bottom left orientate or origin with an orientation so you can use these api's for doing either types of drawing and and generally you would do this because if you create a context it's going to be a bottom left origin base but if a context is given to you by the toolbox so for example if you have a custom view and during its draw carbon event it will pant it will hand you a CG context and that will already be transformed to be top left origin base so that would be normal orientation so also check out session 409 carbonated talk to lock for information about this so why would you want to do this well number one reason is performance I went through personally through many of the controls the standard controls in the system and converted them from using the appearance manager api's over to the new HIV my API and in some cases we were seeing the controls drawing twice as fast with respect to on jaguar most of the common controls will draw twenty-five percent faster so this is solely for performance and you should definitely be using these api rather than old appearance manager api so if you have in your code text drawing we got a lot of feedback about the text drawing performance on Mac OS 10 we want it fast and we've done a lot of work to improve that so if you're going to be drawing user interface text rather than using the old appearance manager api's for getting the text dimensions and drawing which we're getting texts dimensions and draw theme text box you should instead use the new HIC api's HIV and get text dimensions eh I've seen draw text box now this is over twice as fast on Panther than on Jaguar and you can also see that the raw performance of dropping text box is definitely improved but you should definitely be using a chai teen draw text for your user interface drawing not only does it give you better performance but it gives you better control over how you're going to be laying up a text and drawing that in terms of flush pneus truncation and how many lines are going to be drawn now let's say that you're handling text drawing on your own you're using that tsui for your drawing so some tips for using Atsui well keep in mind that that api is a paragraph based api so you should be creating a text layout per paragraph also reuse the layout in the style objects where appropriate rather than destroying a text layout when you're done with it and then recreating another one to set it to look at a new text buffer keep that layout around and then set it to look at a new run of text using the API at Hsu layouts that text pointer so reuse these objects that it eliminates the overhead for a lot of redundant destruction and reconstruction of those those data structures also if you need to lay out a paragraph at a fixed width use the batch API for breaking a line which is f2 batch brake line now of course this is this is rather than manually a break going through a break loop and using the absolute brake line API this will be much faster for doing that also in your drawing text if you need to get the dimensions of that of that text use absolute get glyph balance now this is a good technique also because under the covers it's going to cache the layout for you so a subsequent draw using at to draw text is going to be very fast also you should be creating and associating some fonts all backs with that layout if performance is a concern if you don't specify a font fallbacks object it's going to rely on the system fallbacks which may be expensive to generate and again keep in mind that that's do styles it's not one-to-one with in terms of absolute layouts you don't have to have one per layout so what you'll generally be wanting to do is creating a style and associate that with a number of different layouts okay finally I like to talk about just general responsiveness issues on Mac OS 10 spinning cursor most people are very familiar with this spinning rainbow cursor that's definitely a problem that we want to avoid other parts of your UI may become non responsive while you're tracking the mouse the users tracking a custom control for example and the app becomes on responses think parts of your screen aren't updating maybe the CPU is pegged while you're tracking this which this is a starvation of resources from other utilities that are running on your system or maybe the app is just slow to respond it just feels sluggish now you can find some of these problems using activity monitor in applications utilities and this will allow you to identify the cpu utilization you can see when the processor is pegged which means at or near 100% utilization you can also identify problems using developer applications spin control actually that's a singular and this utility what it will do is when it's launched whenever the system spinning cursor comes up it'll start sampling your app or you'll start sampling that app that has caused that to spin so you can see where the time is being spent and what why did it stop responding also from the command line you can use top so do i identify had to resolve this problem the spinning cursor which seems to be an issue let's understand why this is happening well in general what it is it's being caused because the your app is no longer responding to events so the user has input some keys in the keyboard and in a perfect world all those events gets picked up by your rapid process immediately but sometimes your app is busy your processing loads of information you're looking for intelligent lights and so events that are coming in the system are not being picked up by the by your application so what the system does is it puts up this spinning cursor and that really is correct behavior what it's doing is it's telling the user that your app is not responding anymore if you're an event-driven application and you are no longer picking up event you're not responding and that's correct behavior sort of some solutions for this well the best solution is to call into the event loop and start processing those events and that means that if you're completely harbin event-based and using run application event loop get into that API start allowing events to come into the app so that means to adopt carbon events or because my adopting carbon events the the system takes care the toolbox has a standard event handlers and they'll take care of tracking for you and if there's improvements in the system we can we can give that those improvements to you for free and thread your app if you do need to do heavy duty processing you need to do look for intelligent alien life consider putting that on a worker thread and then continue processing the user events on your main thread and also look for polling of course like a my polling again you use the same utilities as I mentioned earlier you'd be using activity monitors to see when the cpu utilization is at or near a hundred percent or you'd be using top to find out the cpu usage now if the user clicks the mouse and the cpu goes up to being pegged you've got a problem you need to figure out what to do about that there's four main reasons you probably be polling and that's for alternatives for doing this now if you need to track the cursor for example that the users clicked in an area of your view or your custom control and you need to track where the position of the cursor is rather than using the very familiar Wow mouse down get the location of the mouse you would instead use the API track my location and when you call this API the system blocks so rather than pegging the CPU you're being extremely quiet nothing is happening in your app until some user interaction happened when the user moves the mouse this will return and give you an indicator of where the maps location is and what happened why did it why did it returned to the mouse move or does the mouse button come up now if you need to determine where the cursor is on your screen because you want to provide some type of rollover behavior maybe you'd be pulling the cursor location periodically well instead of you doing that you would want to use the API for tracking regions this is a mouse tracking region api's an easy if you guys incredibly cool because they will allow you to specify a region of your window that you are interested in and then you will get notifications via carbon events whether when the mouse is entered and exited that region another reason you may be pulling is because you want to find out when a condition has changed i want to see when preferences have changed or seed value exchange so i know to reload those preferences in so rather than doing that you want to watch for notifications now this is as simple as installing a callback which is essentially what a carbon event notification is you're installing a callback registering for certain notifications to come in and that callback will get called when that has happened so you can watch for notifications like let the system tell you when conditions have changed rather than asking the system continually and finally you may be idly by pulling the system clock and what that means is you want to you you want to wait for a specified time to elapse before continuing execution well rather than pulling the system clock and spinning you would want to use timers now carbon event timers which you would install and have some code executes after this time is left or just jump right into the event loop there's an API called run current event loop and it allows you to specify a time out time so you call that API and your timers will continue to fire at that point and then the execution will proceed when that function returns and finally I'd like to mention a synchronous window dragon this is definitely in the realm of perceived performance this is a new facility for carbon application and it allows the windows server to deal with the trap the dragging of the window now this frees up the app from doing this so if you are very busy and your application has become unresponsive the windows server will take care of dragging the window for you so this will contribute to the feeling that the user is still in control of the system and and there's still things that they can do even when your app is hung so you're probably tired of listening to me talk and so I'd like to bring up the high level toolbox demo boy died bulleted ok so I want to give you a brief example of how you might be able to track down some performance problems in your application and to do that I'm going to use an application we've been working on which is a game now we've been working on this game for a little bit and our beta testers we have this extensive set of beta testers and they've all been complaining about two things one the app launches slowly and two after you play the game actually there's three things too after you play the game the system kind of slows down and get sluggish it's like our app is peeling cycles from somewhere and the third problem is that on slower machines the game doesn't deliver a very good experience the interface gets choppy but to understand this let me go ahead and launch the application I'm going to do it via the command line just because that's going to allow me to more easily do some other tests in a second so if you watch down on the dock this is the application watch it bounce and it's going to take a little while to load up and four or five yeah so it took a couple of ounces so here's the game it's a pin the tail on the donkey game and you know pin the tail on the donkey is pretty easy you just have to drag the tail over to the donkey oh I better start a new game first so I start the game and the count down count actually starts and then I start staring at you and that's actually the challenge of the game can you possibly get the tail on the donkey while I'm staring at you well I did and I got a high score I'm pretty good at it but you know I've been writing it I got to be pretty good at it so that's the game but the main complaint that users have been saying is that it takes a while to launch so let's go take a look at that and there's two ways I want to look at this the first way is through the use of spin control now spin control is one of our performance test tools it will detect when an application is unresponsive and it will automatically sample that application now I know my app is unresponsive during launch those thin control is going to automatically detect that into a sample but I wouldn't necessarily have to you spin control to generate the information I'm going to generate I could use sampler to generate the same information it just so happens that this is a little bit more convenient for my situation so we'll launch it again and as its launching you'll see spin control updated its interface saying hey it was unresponsive and it sampled the app and then I get the results if I double click on that and open it up I can see the back-trace for the time various operations took during out bring up so of course I was in vain for a couple seconds and I was setting up my game window and setting up my high scores dialogue oh and then I started doing some preferences operations well you know it occurs to me that I load my preferences my application preference does it bring up time but most of my preferences is just a high score list I store a really big list of all the scores that have happened on the game and you know the high school it really doesn't matter a tap bring up time the only time I consulted is after the user has played a game and I need to compare and see if it deserves to be on the high scores or if the user displays the high scores window so this real quickly by rethinking the way i initialize my preferences would allow me to cut about a second and a half off of my application launch time so the next thing I want to look at what your sex app launch time is FS usage John talked about FS usage there's a bunch of different options you can pass to it to generate different amounts of information and I'm going to pass the dash W option which generates some extra info about errors and file sizes and things like that and I'm going to pipe that through to grep just so I see the file system operations that happen with respect to my application so if I turn that on and relaunch my application it's going to generate a bunch of information now most of the work that is in this log is stuff happening on my behalf because of the system you know my application executables executable is being loaded and things like that and that's all fine I've already gone through this and looked at one interesting thing now I load some images in my application in the form of PNG files and the first one that gets loaded I don't know if you can read that up there but the first one that gets loaded is called D donkey PNG that's the big donkey image in the window I need that at a purring up because that's you know part of my interface that's fine and then I load the donkey tail and that's cool but I find another load here and it's a title PNG well I don't actually use that title anywhere in my main window I only use it in my rules dialog so that's another way I could I could actually speed up my application launch performance is just load that followed that PNG file only when the user brings up the rules dialog now some of the extra information that the dash W option passes act is the amount of time this particular load took and you can see that it's just a fraction of a second that it took to open that file and there is yeah if I look at the file identifier it's not a whole lot of time spent actually manipulating that file but every little bit counts and if you look for things like this you might actually find that the loading of files at a purring of time is just a symptom of a larger problem so you should go through FS usage find out what sorts of things your application is doing and see if they really need to be done at app launch time so once the application is running and I play a game a finish a game the users say hey you know what subsequent games are either sluggish or my system just completely bogs down and let's go ahead and launch courts to bug here because it's got a little CPU gauge frame meter and oh wow sure enough it looks like my interface isn't doing much but I'm eating up some cpu speed and I'm trying to render overnight frames per second so something's going wrong here there's a couple different ways we can look at my interface and figure out what's going wrong the first way I want to look at is flash identical updates so let's get this out of the way answer oh holy cow okay that's bad i'm redrawing my time display even though the game's not running which is a first first problem but another thing I noticed is that even though the time displays i get rid of it you know even though my text is only about 24 pixels tall I'm REE painting this entire area every time i repaint the text well so this is something I could go in and fix in my in my nib what I should really do is I should shrink up at that field that I'm using to display the time with and that would save me some processing cycles the OS would not need to render quite as much another thing I can look at here with quartz the bug is to flash screen updates so again we're going to see this time rendering constantly which is unfortunate to I'm not playing the game but I would expect that to flash yellow if I actually start a game so let's start a game and see what happens okay so far so good nothing entirely unexpected but as I actually start to drag the tail around wow I'm feeling a lot seeing a lot of drawing happen here and you know what I didn't really intend to do this every time I move the mouse it's repainting the entire donkey picture1 a much better scenario for this game would have been to only repaint the place where the tail was and a place where the tail is now and that's going to save me a lot of time because you know what just the Delta between a tail move and it's old position in position is pretty small I'd probably say easily a 40th of that entire image size so that's going to cut down my draw time there by about a fortieth and that will make my users much much happier and then I can spend my time working on better things like good gameplay so anyway hopefully now you see a couple ways that you can use our tools to identify and track down some of the typical problems in your applications [Applause] Thank You guy that was such a great demo he he's like an excellent program on the toolbox team because of that but finally I'd like to just kind of end up on some general tips now I mentioned earlier that she should cash frequently use information or frequently calculated information with your view as well this is a really important to do for frequently used information or information or data that's very expensive to calculate keep in mind that there is a time and space trade-off and what I mean by that is if you end up cashing 50 megabytes of information and then the user clicks in another application and then the system all of a sudden needs that 50 megabytes it's going to start paging it out to disk and then when the user clicks back into your app it's going to page all that information back in and it may have but just been more efficient to just regenerate that information so just be aware of that the key here is frequently used information or very expensive data to create again always provide feedback now if you're just going to be doing a simple operation put up some chasing arrows for some time consuming applicator time consuming process put a progress bar this I mean if the user thinks that something's going to take 10 seconds because it's going to take them four hours that's something that they should probably know and always allow them to cancel this is really important to let the user be in control of your application rather than your app beam and control of them so finally I just like to point out that that you should get familiar with the performance tools we have in the system there's there's a lot of of utilities on this system and many of which that we haven't talked about it all but get familiar with course debug sampler spin control malice debug shark go check out this session on carbon performance tools also become familiar with the new modern API is the court which you should definitely be using an H I seen use that on Panther take advantage of carbon events this is going to give you more control over your application better performance the advantage of a chive you for all of you custom drawing and keep in mind that we spent a lot of time optimizing the toolbox and other parts of carbon is really everybody's responsibility to keep performance going so finally to go through the roadmap and other reference information I'd like to bring back Xavier right on time excellent thanks Kurt okay we really hope that you guys got like the meetup like what we're trying to achieve here and it gives you a couple of good ideas to go back to your feces and I was really really appreciate if you could spend some time finding out what's going on in your application once again lunchtime try to find out about the drawing we have great tools Aramis we mentioned that we have shark as well which is like very very cool application little bit like sampler that's going to give you ideas as well on how you can optimize specific list of a g5 you know saying edition run some loop maybe you should actually use LT deck in bad part so remember we are the brand new set of tools that can help you identify the hot spots an application to make good usage of it all right just after this session we have the feedback form for like the toolbox encourage you to assist if you had any question if you want to give us your feedback things that you like or think that you really like or figure to really like and think what you don't like okay maybe session three or five on tuning software with performance tools was Wednesday for the visit can travel in time and tomorrow morning we're going to have a great session session 310 on debugging and cleaning carbon applications with others tools will be showing you a couple of cool tricks with Xcode on how to improve the debugging experience how to get the most of your time while debugging carbon application I encourage you to go there oh and I'm forgetting the best of course of the yen session for 25 where I missed your ad will be talking about HIV in-depth HIV was introduced last year actually not in this room but a double the DC it's really the future of like you know during controls on Mac OS 10 and if you have any custom control than your application you really have to go there should you have any questions because I've been changing the slides again anyway should you have any questions please don't hesitate to send me an email exactly at apple.com and I'd be more than happy to let you know find out how we can help you we have some documentation and I encourage you to go on a website on developer audible.com we're revamping completely a website to make it easier for you guys to actually find information so check it out see like you know all the sections that we have uncovered with hiding in the last month or so to the brand new sample code as well for like a chive you look at it inside the carbon sample code and you're going to see two different sections you can have a chai toolbox nhi two books for mac OS x so just check out the HOA books for mac OS 10 section register there a couple of technical notes Mac os10 click your performance to help you find out what's going on with the drawing in Europe and what should you be doing now on mac OS 10 to get the best of performance or drain where things on the file manager and some Q is here available for improving a sweet text drawing you