Which memory number does the system judge your app by, and why do virtual size and “resident” mislead?
Predict first
What happens to footprint and virtual size when you reserve memory and then touch half of it?
import Foundation
import Darwin
func vm() -> task_vm_info_data_t {
var info = task_vm_info_data_t()
var count = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)
_ = withUnsafeMutablePointer(to: &info) { $0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), $0, &count) } }
return info
}
func mb(_ x: UInt64) -> Int { Int(x / 1_048_576) }
let size = 200 * 1_048_576
let before = vm()
let p = mmap(nil, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)!
let reserved = vm()
print("reserved 200 MB, untouched: footprint +\(mb(reserved.phys_footprint - before.phys_footprint)) MB, virtual +\(mb(reserved.virtual_size - before.virtual_size)) MB")
let bytes = p.assumingMemoryBound(to: UInt8.self)
var i = 0
while i < size / 2 { bytes[i] = 1; i += 4096 }
print("wrote to half of it: footprint +\(mb(vm().phys_footprint - reserved.phys_footprint)) MB")
- Reserving raises virtual size by about 200 MB and the footprint by about 0; touching half raises the footprint by about 100 MB
- Reserving raises the footprint by about 200 MB at once
- Touching memory changes neither number
Mental model. Virtual size is the area of land you have fenced off. Footprint is the area you have actually built on. The planning office (jetsam) taxes the built area, and it counts what you squashed into the basement (compressed memory) as built too.
A process has several sizes. Virtual size is the address space you have reserved: in the check, mapping 200 MB with mmap raised it by about 200 MB and raised the footprint by 0, because no page had been touched. Resident size counts pages currently in RAM, but on iOS there is no swap file, so unused dirty pages are compressed instead of written out, and resident undercounts them. The number the system acts on is the physical footprint (phys_footprint in task_vm_info): dirty pages plus compressed pages plus some kernel-attributed memory, excluding clean file-backed pages the system can simply drop. Writing to half of the mapping raised it by about 100 MB. That footprint, compared with a per-device limit, is what jetsam enforces (Q227); Xcode’s memory gauge and Instruments’ “VM Tracker” and “Allocations” report it from different angles.
Consequences for design: reserving address space is cheap, touching it is what costs; memory-mapped files and clean, re-creatable caches are cheap because the kernel can drop them (NSCache, mmap of read-only data), while decoded bitmaps (width × height × 4 bytes, regardless of the JPEG’s file size) are dirty and expensive. On a device you can ask how much headroom remains with os_proc_available_memory(), a better guide than the memory-warning notification (Q226), which is advisory and may not arrive before a kill. The per-app limit depends on the device’s RAM, the entitlement “increased memory limit” and whether the app is in the foreground, and Apple does not publish it as a constant, so measure on the lowest-RAM device you support. The simulator uses the Mac’s memory and has no jetsam limit, so a footprint problem cannot be reproduced there; the check above ran on macOS and shows how the counters behave, not what the iOS limit is.
Pages count against the footprint only once they are dirty (or compressed), not when address space is reserved.
Common traps
- Reading “virtual memory” in a tool as the app’s memory use. It includes reservations and shared mappings that cost nothing.
- Sizing images by file size. A 200 KB JPEG decodes to width × height × 4 bytes; downsample at decode time.
They might follow up with
- Why is clean memory cheaper than dirty memory? The kernel can discard clean file-backed pages and reload them, but dirty pages must be kept or compressed.
- What does the increased-memory-limit entitlement do? It asks the system for a higher ceiling on supporting devices; it is not a guarantee, and it does not make the footprint free.
Related questions
- 6.6.1 What should an app do on a memory warning, and how reliable is the warning?
- 6.6.2 What is jetsam, and how does it differ from a crash?
- 6.9.1 How does a process end, and which signal or exit status does each kind of failure produce?
← How does a process end, and which signal or exit status does each… How is the sandbox actually enforced, what does a denied operation… →