iOS applicationDidReceiveMemoryWarning triggered most frequently at ~1.8 GB memory usage, but less often when memory is higher — why?
On iOS, is triggered very frequently when memory usage is around ~1.8 GB, but the trigger rate actually decreases once memory usage goes higher. What causes this behavior?
This behavior is consistent with iOS’s tiered memory pressure response model. The root cause is that applicationDidReceiveMemoryWarning is not triggered by an absolute memory usage threshold, but rather by a relative memory pressure evaluation performed by the system. The decision is made dynamically based on available memory headroom, background process contention, and overall device memory pressure. Detailed explanation 1. The trigger mechanism is based on memory pressure levels, not absolute memory usage iOS does not use a fixed memory value e.g. 1.8 GB as a hard trigger point. Instead, it monitors global memory pressure via mechanisms such as vm pressure level. A memory warning is sent to the foreground app when the system detects conditions like: Rapid depletion of free memory pages especially active / non pageable memory Aggressive eviction of background apps to reclaim memory File cache or compressed memory reaching saturation → At this stage, iOS sends applicationDidReceiveMemoryWarning to prompt the app to proactively shed memory. 2. Why ~1.8 GB often shows high frequency warnings This memory range typically corresponds to a “salvageable critical zone”, where: The app has already loaded most major assets textures, meshes, audio , but has not yet triggered Resources.UnloadUnusedAssets or unloaded AssetBundles Both the native heap and managed Mono heap continue to grow, while GPU/driver memory pools e.g. Metal / OpenGL texture caches approach saturation The system still preserves some background memory buffers, making memory pressure signals more sensitive and frequent In this zone, iOS still expects the app to cooperate and release memory voluntarily. 3. Why warnings decrease at higher memory usage e.g. 2.2 GB ⚠️ This does not mean the system becomes more tolerant. Instead, the app has entered a more dangerous phase: iOS has already initiated aggressive countermeasures: terminating background apps, compressing inactive pages, and reclaiming file cache If the app continues allocating memory, the system may skip warnings entirely and proceed directly to SIGKILL OOM termination As a result, applicationDidReceiveMemoryWarning occurs less frequently because the system no longer attempts negotiation—it moves straight to silent termination Verification & optimization recommendations Use Xcode Instruments → Activity Monitor to inspect Real Memory alongside Memory Pressure curves, and confirm correlation with rising vm pressure In Unity’s OnLowMemory callback, immediately: Call Resources.UnloadUnusedAssets and explicitly destroy unreferenced textures via Texture2D.DestroyImmediate Switch to lower tier assets e.g. ASTC 4×4 instead of 8×8 Persist critical game state to avoid data loss in case of termination Cap peak memory usage by analyzing GPU / Resource / Mono reports in GameOptim's GOT Online, and identify major memory consumers oversized atlases, unloaded AssetBundles, Mono heap growth Conclusion This behavior is a normal manifestation of iOS’s memory protection strategy. Frequent memory warnings indicate that the app is in a recoverable critical window, where effective resource lifecycle management can still prevent termination. Lack of warnings at higher memory usage usually signals that the app has crossed into a non recoverable zone. You may refer to the AI analysis above. In practice, the warning indeed tends to occur around ~1.8 GB, and the reduced trigger rate at higher memory usage follows the same underlying mechanism.