iOS app terminated due to memory pressure - ios

I am trying to use image files with my app. These image files are compressed in a .zip-file which is opened from the user from the Mail App or Safari. The .zip-file (which contains the image files) is then unzipped by "SSZipArchive". This works without any problem for smaller files (e.g. 5 images, 10KB). But for bigger files (1900 images, 20MB) the app crashes and it is hard to figure out why because it only crashes when the app is not debugging and not watched by Instruments. A few times I got a crash while using the debugger but only when I opened the .zip-Archive from the Mail App. I then got the message "App terminated due to memory pressure".
Please help!

You're probably testing on the Simulator. That's never reliable, because your computer has lots of memory! Test on the device to find out under real-life conditions whether your app uses too much memory. If it does, you'll get a warning and then (if you don't do something about the problem) a deliberate termination.

The root of your problem is that you simply cannot allocate that much memory under iOS or your app/device will crash. A good rule of thumb is that you app might take 10 to 20 megs of memory while running normally, but if it jumps up to 40-80 at any point then you will be in danger of a crash. You should read up on how much memory images use when decompressed under iOS mem blog post and rework your code to make sure things stay in the 10 to 20 meg of memory usage range.

Related

What amount of memory should I target for my iOS app?

I am currently showing that my app is using a maximum of 200MB when it is running. Is there a way to tell if this is going to trigger a low memory warning? So far I have not had any issues with the simulator or actuall devices.
We must avoid spiking the memory. For example loading images from disk or cache in loop. This will create a memory spike and it is at this point iOS starts to throw low memory warnings. The exact amount of memory is not specified by Apple. In many applications I have observed that as the memory grows gradually iOS is comfortable and app works properly. But if memory spike occurs low memory warning is thrown.
Apps can use 200 MB of memory these days easily, how ever it is important to simulate and handle low memory warnings in order to be on the safe side.
If you want to trigger low memory warning using simulator, there is a option of doing so in the Menu->Debug of Simulator (Cmd+Shift+M). In device you may load some big images in a for loop. You may also call a private method.
[[UIApplication sharedApplication] performSelector:#selector(_performMemoryWarning)];
Just be sure that this code does not go to production as Apple will reject the binary as private method is being used.

How to detect an OS forced App Shutdown

I am working on a iOS Application for >=iOS8 Devices. My app is memory intensive which becomes a problem since the app can crash. I have CrashLoggers in place that report crashes on the app during the next start. However there are certain scenarios when the app may consume higher than usual memory and the OS may terminate it. Is there any delegate that I could use to detect an OS forced app termination?
I tried [AppDelegate applicationWillTerminate:] and [AppDelegate applicationDidReceiveMemoryWarning:] but they are going to give me false positives for the most part. The problem is that this is not a exception, but a system signal raised by OS to kill the app that I am trying to detect within the scope of the event.
I am a new programmer. Let me know if I am understanding things incorrectly or I am making impractical assumptions.
I have read the following links:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationWillTerminate:
Is there any method in appDelegate which is called when application crashes?
I understand that preventing the problem is better than cure. But here I am trying to detect if there's going to be a problem. It's not like the app always crashes. There may be some edge case scenarios or users on very old devices like iPhone 4s/iPad Air 1 for which the app can run (possibly) into problems. So, I need a logging mechanism around this.
The runtime of the app is ~120MB worst case which is high but well under the range of too high. While the app has a lot of features, Image processing in the app is difficult to perform while maintaining the quality and also to profile in terms of memory(spikes depend on size, quality of image, lighting, etc.). So my app is well within the boundary line, and I am asking for way to detect if the app crosses this boundary when used by the user.
I totally agree with optimization(or fixing the crash) suggestion that you gave, and I would try my best to optimize(or de-bug) the app.
When app crashes or is killed by the system, there is no signal that you can catch meaningfully.
What makes you think applicationDidReceiveMemoryWarning: is giving you false warnings?
Receiving a memory warning and then not being killed is not a false positive. That just means your app didn't increase memory allocations enough to cross the threshold.
When you receive a memory warning, log if you want, but also decrease memory usage.
How do you know that the maximum runtime allocation footprint is 120MB? Depending on device, you'll have anywhere from around 125MB (iPad 1) to well over 1GB of memory available on modern devices (more on iPad Pro).
You should be getting your applicationDidReceiveMemoryWarning: called when the system is under memory pressure. This can be simulated by selecting the Simulate Memory Warning menu item in the Hardware menu.
If you actually go over your memory limit on device, you'll get jetsamed (SIGKILLed). You can't detect that.
If you want to simulate the jetsam, just send your process a SIGKILL (kill -9 <pid>)

iOS - applicationDidReceiveMemoryWarning - Why?

I'm working with a Unity project that is running on my iOS devices via Xcode, and I'm currently getting the error:
applicationDidReceiveMemoryWarning()
Every second. Yet my memory usage is around 40Mbs, which is 4% of my memory. So how am I getting a memory error? It's also the only app running. There are no other apps running in the background.
Please advise?
Thanks.
I've seen situations where allocated a lot of memory at once (or a lot of small amounts of memory quickly) will cause the app to receive memory warnings. Not sure why that's the case as you'd think it would be ok until you started using too much in total but maybe iOS doesn't like it as it could affect performance of other apps or the OS itself.

Photo Editing extension needs lots of memory and got crashed. How to avoid it?

We've developed a Photo Editing extension to edit user's photos. But the photos which user take have large high-resolution. When editing them in extension, it will cost about 100-200MB memory and extension get crashed. But we can't reduce user photo's resolution, how to apply more memory in Photo Editing extension?
I have the same problem. I'm writing an extension to complement my photo editing app. My filter pipeline is relatively complex; it uses a maximum of 6 image-sized textures at a time. However, in the main app I can even process the full camera image size of 8 MP (iPhone 5s) without running into memory issues.
In the extension, I use the display-sized image given by the framework for displaying the preview of the filter to the user, which works perfectly fine. But when I try to apply my filter to the original image as soon as the user taps Done, the extension crashes with the error message Terminated due to Memory Error (in Xcode). I even refactored my shaders and texture management code to only use half (!) of the previous amount of memory, but the extension keeps crashing.
I know Apples guide explicitly mentions lower memory limits:
Memory limits for running app extensions are significantly lower than the memory limits imposed on a foreground app. On both platforms, the system may aggressively terminate extensions because users want to return to their main goal in the host app. Some extensions may have lower memory limits than others: For example, widgets must be especially efficient because users are likely to have several widgets open at the same time. [...]
Keep in mind that the GPU is a shared resource in the system, and so app extensions don’t get top priority. For example, a Today widget that runs a graphics-intensive game may give users a bad experience on both platforms and is likely to be terminated because of memory pressures.
But I don't see how complex photo editing apps are supposed to work with that. The current memory constraints are clearly too high. The only option I see right now is to reduce the image size when saving results and prompt the user about it and tell him/her to use the main app for hi-res export ... which totally misses the point of the extension. I hope Apple will raise the limits before the final release of iOS 8.
UPDATE
I just updated to the iOS 8 GM release and the GM release of Xcode 6. Now everything works perfectly fine! I am able to process 8 MP images without any memory warning now.

iPad1 memory mystery with my texture-intensive game app

Sorry for the vague title, but not quite sure how to summarize this one.
The facts are:
I have a game that's been approved by Apple and is on the App Store.
It is a universal app. It uses textures designed for 320x480 on small screens, and uses larger textures (roughly four times as large) on retina and iPad screens.
While developing it, I would sometimes see low-memory warnings in the console log, but after reading about these it seemed like they were often somewhat spurious/unimportant, and in any event I was not having crashes, and my testers on a variety of devices (iPod Touch 2nd gen, iPod Touch 4th gen, iPhone3, iPhone4, iPad1, iPad2) were not seeing crashes.
When I started distributing the app to a wider set of beta testers through TestFlightApp, I got reports of some people seeing crashes as the app was loading, or very early after the user had chosen a level from the main menu and the app was loading the level textures. We discovered that if these users just restarted their devices, they didn't have problems any more. Since this was the first time we had seen problems like this, we attributed it to something TestFlightApp was doing, some funny state it was leaving the device in after the install (we talked to TestFlightApp about this and they had never heard of such a thing).
As stated, Apple approved the app and it's on the App Store. Soon after it went live, we got reports from some iPad1 users that it was crashing for them on app load, or soon thereafter, same kind of thing as we saw with certain TestFlightApp users. And again similar to the TestFlightApp users, these customers reported that restarting would often fix the problem. But it wasn't as nice because the problem tended to appear again. One of these users sent me several LowMemory...log files that she got off her PC after synching her iPad. There were about 10 such files, and none of them listed my program in the Processes list. Instead it showed other programs marked as either (active) or (jettisoned), and the "Largest Process" could be anything from MobileSafari to Kobo, but again my own app was never listed. So, I didn't understand that, but the bottom line seems to be that, for this user at least, something is pushing the memory over some limit where my app won't run well.
I have since gone back and talked to one of the TestFlightApp beta testers, and it turns out that he does indeed sometimes get the app crash again, so it wasn't just some residue from TestFlightApp. However, for him the crash is much less frequent than it is for this customer.
Other iPad1 testers of the game have never had any trouble. They report that they play the game for hours each day, use their iPad with several other apps in between, and rarely power it down. Similarly, I never had a crash with my iPod Touch 4th gen, which is similar to the iPad1 in the at it has a hi-res screen but only 256k RAM.
So, it's very mysterious to me what could be so different about these particular users' iPads. It's mysterious that the game works after the device is restarted, but then after some apps have been run the game (sometimes) has trouble loading. My understanding was that if my game demands memory, the OS will auto-close whatever other apps are running, as necessary, to effectively bring the amount of memory back up to the amount that's available on a freshly restarted device. My only conclusion is that after running some apps the device is left in a state where less memory is available because the OS cannot reclaim certain memory blocks or shut down certain apps.
Unfortunately I don't have one of these "misbehaving" devices to develop with. All I can think to do is try to reduce the memory needs of my app by a certain amount, and send it to one of these users who is having trouble and see if it fixes things. That seems like a potentially inefficient approach, however.
Anybody have a better idea?
Sounds like the memory spike during texture loading is what's causing the app to be terminated on some devices. It may well use less memory after everything's loaded than it does right near the end of initial loading. This could be explained by things being pushed to virtual memory, whereas direct texture loading could be bombarding the RAM with way too many allocations. My suggestions would be to:
Be more aggressive with destroying temporary data structures during loading (release a temporary structure the instant all of its useful values have been read/extracted by other things)
For autoreleased objects, keep an NSAutoreleasePool around at all times; you may even want to drain and realloc a pool several times over the course of one method if you use an exceedingly high number of autoreleased objects.
This may sound silly.. intentionally slow down your loading process. If you get rid of parallelized loads (loading multiple objects at once) or possibly insert a manual time delay in your loading thread/methods, this may give the OS more time to push things to virtual memory and thus Watchdog will not detect the app as being a RAM hog.
EDIT: One possible tactic to implement slower loading: if/when you receive a low memory warning, pause or slow loading down for a few seconds to give other apps time to lower their memory usage, then continue loading at normal speed.
Even if I'm wrong (if LowMemory...log files show Virtual+Physical usage and thus your app isn't even doing that much), I would suggest then integrating bug reporting such as QuincyKit so that you get emailed a backtrace and crash description when this bug IS encountered in the wild.

Resources