Locating Memory Issues in Your App
Managing the memory that your app uses is one of the most important aspects of creating an app. From the smallest iOS device to the largest OS X computer, memory is a finite resource. This chapter describes how to identify common memory issues, from memory leaks to zombies.
Examining Memory Usage with the Activity Monitor Trace Template
The Activity Monitor trace template monitors overall system activity and statistics, including CPU, memory, disk, and network. It also monitors all existing processes and can be used to attach new instruments to specific processes, monitor parent-child process hierarchies, and to quit running processes. It consists of the Activity Monitor instrument only. You’ll see later that the Activity Monitor is also used to monitor network activity on iOS devices.
The Activity Monitor instrument provides you with four convenient charts for a quick, visual representation of the collected information. The two charts that describe memory usage are:
-
Real Memory Usage (bar graph). Shows the top five real memory users in a bar graph.
-
Real Memory Usage (pie chart). Shows the top five real memory users with the total memory used displayed.
Figure 7-1 shows the top five users of memory on the system.
Activity Monitor instrument with chartsThe following configuration options provide memory-specific information through the Activity Monitor. For statistic definitions and complete configuration options, see “Activity Monitor Instrument” in Instruments User Reference.
-
Physical Memory Wired
-
Physical Memory Active
-
Physical Memory Inactive
-
Physical Memory Used
-
Physical Memory Free
-
Total VM Size
-
VM Page In Bytes
-
VM Page Out Bytes
-
VM Swap Used
Recovering Memory You Have Abandoned
The Allocations trace template measures heap memory usage by tracking allocations, including specific object allocations by class. It also records virtual memory statistics by region. It consists of the Allocations and the VM Tracker instruments.
Avoid abandoned memory by ensuring that the heap does not continue to grow when the same set of operations are continuously repeated. For example, opening a window then immediately closing it, or setting a preference then immediately unsetting it are operations that conceptually return the app to a previous and stable memory state. Cycling through such operations many times should not result in unbounded heap growth. To ensure that none of your code abandons memory, repeat user scenarios and use the Mark Heap feature after each iteration. After the first few iterations (where caches may be warmed), the persistent memory of these iterations should fall to zero. If persistent memory is still accumulating, select the focus arrow to see a call tree of the memory. There you can identify the code paths responsible for abandoning the memory. Ensure that your scenarios exercise all your code that allocates memory.
If the heap continues to grow after the first few iterations of the cycle, you know your app is abandoning memory. Find a heapshot that seems representative of the repeated heap growth. Click the focus button to the right of the heapshot name to display objects created during that time range that are still living after the app has executed.
After you stop the trace, you can still take snapshots by dragging the inspection head in the trace window timeline to where you want the snapshot, and clicking Mark Heap. After stopping the trace, take one last snapshot at the end of the trace. At that point, the number of persistent objects should be zero.
Finding Leaks in Your App
The Leaks trace template measures general memory usage, checks for leaked memory, and provides statistics on object allocations by class as well as memory address histories for all active allocations and leaked blocks. It consists of the Allocations and Leaks instruments.
Use the Leaks instrument to find objects in your app that are no longer referenced and reachable. The Leaks instrument reports these blocks of memory. Most of these leaks are objects and are reported with a class name. The others are reported as Malloc-size.
Note: If a leak isn't an object, you may be calling an API that assumes ownership of a malloc
-created memory block for which you are missing a corresponding call to free().
After opening Xcode to see the piece of code that is creating the leak, the cause of the leak may still be unclear. The Leaks instrument allows you to see the cycle that is creating the leak in the Cycles & Roots option in the Detail pane. It provides a graph of the reference cycle that is causing the leak.
Eradicating Zombies with the Zombies Trace Template
The Zombies trace template measures general memory usage while focusing on the detection of overrelease “zombie” objects. It also provides statistics on object allocations by class as well as memory address histories for all active allocations. It consists of the Allocations instrument only.
The Zombies template substitutes an object of type NSZombie
for objects that are released to a reference count of zero. Then, when a zombie is messaged the app crashes, recording stops, and a Zombie Messaged dialog appears. Clicking the focus button to the right of the message in the Zombie Detected dialog displays the complete memory history of the overreleased object.