Article

Reducing the Memory Footprint of Metal Apps

Learn best practices for using memory efficiently in iOS and tvOS.

Overview

Efficient memory usage is a critical consideration for resource-intensive Metal-based apps in iOS and tvOS. Apps should use as little memory as possible, making more memory available for other apps and system services.

iOS and tvOS monitor your app’s total memory usage at runtime, and if the amount exceeds a predetermined limit, the system terminates your app. This limit varies by device model, so be sure to test your app on all supported devices.

Understand Changes in Memory Accounting

The accounting for purgeable, nonvolatile memory changed beginning in iOS 12 and tvOS 12. In iOS 11 and tvOS 11, allocations with this memory storage mode—commonly used by Metal apps to store buffers, textures, and state objects—weren't counted toward an app’s memory limit and weren't presented in tools like Xcode memory gauge. It was possible for an app’s actual memory usage to exceed certain predetermined memory limits without being terminated.

In iOS 12 and tvOS 12, if an app is built with the iOS 12 or tvOS 12 SDK, such allocations are counted toward the app’s memory usage limit. As a result, the system can now more accurately monitor an app’s total memory usage. If an app exceeds the limit, it's now likely to be terminated on devices running iOS and tvOS versions 12 and later.

As of March 27, 2019, all new apps and app updates for iPhone or iPad, including universal apps, are required to be built with the iOS 12.1 or later SDK and support iPhone XS Max or iPad Pro (12.9-inch, 3rd generation). If you have difficulty reducing your app’s memory requirements, contact Apple Developer Support to request an entitlement for your app to use iOS 11–style memory accounting.

Optimize Memory Usage in Your Metal App

Here are some tips for understanding how your Metal app is using memory, and best practices for reducing memory usage.

Use Xcode 11 to measure memory consumption. Build your app with the iOS 13 or tvOS 13 SDK, then use Xcode memory gauge to observe your app’s total memory footprint during execution.

Use these tools to gain a deeper understanding of your app's memory footprint.

Make your assets as small as possible. Avoid loading a large resource when a smaller one will do. Use compressed texture formats. Load lower-resolution textures when running on memory-constrained devices. Consider reducing the fidelity of 3D models and compressing per-vertex data.

Simplify memory-intensive special effects. Some effects, like shadows or motion blur, require large offscreen buffers for temporary image data. Consider lowering the resolution of these image buffers or applying fewer effects when running on memory-constrained devices.

Avoid loading unused resources. Xcode can help you identify Metal objects that aren't in use. Use the Frame Capture Debugging Tools to take a frame capture. Then navigate to the Metal Memory Viewer, and select the Unused filter.

Designate resources as volatile when possible. Use MTLPurgeableStateVolatile and setPurgeableState: for textures and buffers whose underlying memory could be discarded under low-memory conditions, and subsequently recreated or reloaded as needed. This allows your app to keep a cache of idle resources in memory while avoiding counting them toward the memory limit.

Use memoryless texture storage for temporary render targets. MTLStorageModeMemoryless avoids allocating regular system memory, allowing apps to store the contents of temporary render targets directly in tile memory on the GPU.

Use Metal resource heaps. MTLHeap allows multiple Metal resources to be backed by the same memory allocation. For example, you can use resource heaps when transient resources are produced and consumed for each frame but aren't all used together. Those not used together can share the same memory, backed by a heap.

Additional Resources

The WWDC video Delivering Optimized Metal Apps and Games provides additional information about the latest memory debugging tools and best practices to help you optimize the memory footprint of your Metal apps and games.

See Also

Resources

Setting Resource Storage Modes

Set a storage mode that defines the memory location and access permissions of a resource.

Copying Data to a Private Resource

Use a blit command encoder to copy buffer or texture data to a private resource.

Synchronizing a Managed Resource

Synchronize the contents of a managed resource for the CPU or GPU.

Transferring Data Between Connected GPUs

Use high-speed connections between GPUs to transfer data quickly.

MTLResource

An allocation of memory that is accessible to a GPU.

MTLBlitCommandEncoder

An encoder that encodes memory copying, filtering, and fill commands.

MTLResourceStateCommandEncoder

An encoder that encodes commands that modify resource configurations.

Buffers

Create and manipulate unstructured GPU resources.

Textures

Create and manipulate structured GPU resources.

Indirect Command Buffers

Recoup encoding time by reusing commands, or create a GPU-driven rendering pipeline by generating commands on the GPU.

Heaps

Create a single allocation of memory from which you can suballocate resources.

Synchronization

Manage access to resources in your app to avoid data hazards.