The term “performance” may mean different things to different people. So before embarking on a quest to improve the performance of your application, now is a good time to consider what this term means.

Many people equate performance with speed. Indeed, if a program performs a complex operation in one second, you might think the program has good performance. Taken by itself, though, speed can be a misleading measurement. In complex software systems, the speed of an operation is not a fixed value. If you perform the same operation several times under different conditions, the time it takes to complete that operation could vary widely. That is because the program is only one of many processes sharing resources on the local system, and the use (or abuse) of those resources affects all other processes.

The following sections explain performance in terms of two different concepts: efficient resource usage and perceived performance. Both of these concepts have an important impact on how you design and implement your application, and understanding how to use both can lead to better overall performance.

The Efficient Use of Resources

A computer shares a limited number of resources among all the running processes. At the lowest level, these resources break down to the following categories:

CPU time

Memory space

Mass storage space

All of your data resides either in memory or on some sort of mass storage device and must be operated on by the CPU. An efficient application uses all of these resources carefully. The following sections provide more detail about each type of resource and its effects on your programs.

CPU Time CPU time is doled out by the system so you must make the best possible use of what time you have. Because both OS X and iOS implement symmetric multiprocessing, each thread on the system is assigned a slice of time (maximum of 10 milliseconds) in which to run. At the end of that time (or before in many cases) the system takes back control of the CPU and gives it to a different thread. On a typical system with many active threads, if every thread used its full allotment of time, performance would be terrible. This leads to one of the most important goals for writing an application: Goal:If your program has nothing to do, it should not consume CPU time. The best way to accomplish this goal is to use an event-based model. Using modern event-handling systems, such as the ones found in Cocoa and iOS, means your program’s threads are run only when there is work to be done. When your application does have work to do, it should use CPU time as effectively as it can. This means choosing algorithms that are appropriate for the amount of data you expect to handle. It also means using other system resources, such as an available vector unit (AltiVec or SSE in OS X) or a graphics processor, to perform specialized operations, which leads to the following goal: Goal:Move work out of the CPU whenever you can. For basic information about how to use CPU time effectively, see Fundamental Optimization Tips. For tips specifically related to improving the speed of drawing operations, see Drawing Code.

Memory Space Memory on modern computing hardware is typically composed of progressively slower (but larger) types of memory. The fastest memory available to the CPU is the CPU’s own registers. The next fastest is the L1 cache, followed by the L2 and L3 caches when they are available. The next fastest memory is the main memory. The slowest memory of all consists of virtual memory pages in OS X that reside on disk and must be paged in before they can be used. In an ideal world, every application would be small enough to fit into the system’s fastest cache memory. Unfortunately, most of an application’s code and data resides either in main memory or on the disk. Therefore, it is important that the application’s code and data is organized in a way that minimizes the time spent in these slower media, which leads to the following goal: Goal:Reduce the memory footprint of your program. Reducing the memory footprint of your program can significantly improve its performance. A small memory footprint usually has two advantages. First, the smaller your program, the fewer memory pages it occupies. Fewer memory pages, typically means less paging. Second, code is usually smaller as a result of being more heavily optimized and better organized. Thus, fewer instructions are needed to perform a given task and all of the code for that task is gathered on the same set of memory pages. In addition to reducing your application’s memory footprint, you should also try to reduce the footprint of writable memory pages in your application. Writable memory pages store global or allocated data for your application. In OS X, such pages can be written to disk if needed, but doing so is slow. In iOS, the contents of these pages must be purged manually by the application itself, which might later require the application to recreate the data that was on those pages. In both cases, the system’s efforts to free up memory take time—time that could be better spent executing your application code. For basic information about how to reduce the footprint of your program, see Application Footprint. For tips specifically related to using memory more efficiently, see Memory Allocation Code.