I have some general questions about what happens to app memory.
What happens to memory when the app enters the background or suspended. I'm asking this because my app has some memory leaks that are, from my research, bugs in Apple's framework and not due to my coding. The leaks are fairly small, (~100bytes), so they should not disrupt performance. However, I was wondering what happens to these leaks when the user stops using the app? Do they go away or do they just stay forever in the phone's memory?
Also, another very similar question, except with retain cycles. Do retain cycles get resolved when a user quits an app, assuming they are not a big of a problem to crash the app while in use?
So, in short, when a user quits an app, do allocations and memory get reset to 0, is what I'm trying to ask.
Thanks for your help!
The answer is complicated.
An app can be in a variety of states:
Active
Inactive
Running in the background
Suspended
Not running
In all but the "not running" state, the app is in memory and your memory leaks continue to accumulate.
Normally, when your user presses the home button, the app quickly transitions through inactive (still running in the foreground but no user interaction) to background (still running but another app has focus) and to suspended (in memory, but not getting any processor time. Your code isn't being called at all in this state.) You get a notification as the app moves to inactive and to the background state, before it goes to the suspended state.
You're expected to save whatever information you need to save in response to the applicationDidEnterBackground message.
Once the app is in the suspended state it can be terminated without any further warning. If you haven't saved your information to a file at that point, it's lost.
If the app stays in the suspended state and then gets woken up to one of the running states, all of your in-memory objects are still around, and your memory leaks are still accumulating.
As #blobbfuesch says, memory leaks cause your app to use up more and more of the device's RAM. If your memory use gets to be too much, the system will issue you one or more memory warnings, and if you don't free up enough memory, it will terminate you.
Because leaked memory is lost, you CAN'T free it up. Even small leaks add up. If the user keeps your active long enough, they accumulate and can cause your app to be terminated, which looks like a crash to the user.
If the app is terminated while in the suspended state, it gets unloaded from memory and has to be relaunched the next time it's run. in that case the previously leaked memory gets recovered, but then it starts leaking again.
If your app enters background, iOS will not change your apps memory but tell your app to release memory as new memory is needed by sending memory warnings. Most of Apples frameworks which you use in your app like UIKit and MapKit will also release memory in this case.
All memory which was allocated by an app gets released when the app terminates. This includes retain cycles and memory leaks. Retain cycles are bad because they lead to a bigger memory consumption of your app. Apps running in background get terminated earlier, if they use more memory. If an app uses too much memory in the foreground, iOS will also terminate your app so you should always break retain cycles in your app by using weak references to prevent iOS from terminating your app too early.
As all memory is deallocated when the app is terminated, retain cycles are resolved when the app quits. however if you start it again and the same code is executed, your app will create the same retain cycle again.
Related
I'm having issues with my WKWebViews'cache being purged sometimes when a user hasn't been using my app for a while.
I guess, that's because iOS puts my app in Suspended and then a low-memory condition occurs so my app is purged.
I read Apple's documentation about The App Life Cycle - Execution States for Apps
Especially the part describing the Suspended state :
Suspended - The app is in the background but is not executing code. The system
moves apps to this state automatically and does not notify them before
doing so. While suspended, an app remains in memory but does not
execute any code. When a low-memory condition occurs, the system may
purge suspended apps without notice to make more space for the
foreground app.
Two questions here :
1) What does "purge" mean exactly ? The app is killed ? Or does it still appear on the app selector ( when double-tapping the home button )
2) Here we can see that there is no way to know when an app is going to be suspended. All right. But if a user comes back to the app, is there a way to know, then, that the app has been suspended ? I can't find any UIAppDelegate's method to do so, but there might be another solution ?
Purge - The purge command forces disk and memory caches to be emptied,
offering a ‘cold disk buffer cache’ which is similar to the state of
the operating system after a reboot.
Referenced from here
As per the documentation
applicationDidEnterBackground:—Lets you know that your app is now
running in the background and may be suspended at any time.
This is the only method which will let you know that method may will enter in Suspended State
also
application:didFinishLaunchingWithOptions: will let you now that
your app's launch process is almost done and the app is almost ready
to run.
The app is in the background but is not executing code
I think it's explained good by Apple, the app is still in memory but no background threads are executed since foreground app requires more resources. Maybe when memory is restored, your app can execute background code again if has not been killed by OS.
When low-memory condition occurs, you're app could be killed (purge).
Is there a way to know, then, that the app has been suspended?
When app is killed from OS, next launch is equal to a complete new restart of app. For this AppDelegate doesn't provide a method to achieve this. You could set a flag in UserDefaults when app goes in background and then make some logic on that flag.
This question might have been asked before but i couldn't find an answer. If i open an app and press home button it goes in background and if i open it again it calls app delegate methods such as "applicationWillEnterForeground". How long it will take me to be in background so app calls didFinishLaunchingWithOptions and starts the fresh app?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Thanks
There are many factors that are taken under consideration to remove your app from the memory (kill the process).
The most simple one is rebooting the device. All apps are off after a reboot. Apps with Voip however are launched automatically into the background after a reboot.
The second and most common one is memory pressure. If your app is in the background and system runs out of RAM, it kills the suspended apps starting from the one that consumes the most RAM and keeps killing them until it reclaims enough memory.
Another, quite common one is something known as the watchdog. There are specific scenarios when your app's main thread has a limited time to finish the task. For example, when you app returns from the background or when the user presses the home button, you have about 10s to free the main thread. (Keep in mind there are situations such as background tasks, music playback and other, that grant your app more execution time in the background).
But, a typical app will be killed if the runloop does not return in about 10.
Another case worth mentioning is if your app uses very little RAM. It was mentioned in one of WWDC sessions, that if your application consumes no more than 16MB of RAM, it will be dumped to flash storage, and restored back to the memory on reopening, rather than being killed. So in this case your app may never be killed (I'm not sure about the reboot, but I assume the dumped image is ignored after a reboot and a normal launch process happens).
Next one is the user's explicit action, that is entering the multitasking UI and swiping the app upwards, which will kill the application.
I think that sums up the most common scenarios.
And of course you might also want to have a look at the docs: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1
How much RAM does the device have? Have much RAM was your app using? Are you following best practices when your app receives didReceiveMemoryWarning:? Are you opening other apps before going back to yours? This is such a "it depends" question.
What's the larger question here? Why do you want to know when your app will get purged from memory?
Is there a any chance that an in memory data might be lost when an iOS app goes to background?
for example if the OS give notice to the app with
didReceiveMemoryWarning and the app didn't take any action to release some space.
so far I have never notice this.
Not instantly, but the app may be terminated at any point, if other apps are used and the system decides, that it needs the memory blocked by your app.
In a question I asked several months ago, I asked if the effect of Jetsam on memory usage can be observed. I answered my own question using instruments, finding that apps killed by Jetsam still had the same memory footprint that they had before they were terminated.
Even today, I still see jettisoned apps in the running task bar recently-used app list. I don't get any performance improvement unless I remove them myself, even after Jetsam has killed them.
If that's the case, what is the purpose of Jetsam and what is it doing (other than killing apps)? I don't see any benefits. Is this a bug?
Even today, I still see jettisoned apps in the running task bar. I don't get any performance improvement unless I remove them myself, even after Jetsam has killed them.
Poppycock. There's no such thing as a "running task bar". You're thinking of the list of recently-used apps. The presence of an app in this bar does not indicate that the app is still running, and removing killed apps from this bar has no effect on performance/memory. The only thing removing an app does from this bar that is beneficial is it kills the app if it was still running.
As for jetsammed apps, it's not surprising that the app will have the same memory footprint after it's relaunched. Apps are typically jetsammed because they're suspended and the foreground app needs more memory. The fact that an app is jetsammed does not indicate that the app was necessarily using an unacceptable amount of memory.
As it turns out,
When a program leaves the forground it goes into a "suspended" state. The OS will then keep the memory around for that application as long as the OS doesn't need it for something else so the program loads faster.
Jettison works the same way: it FREES UP memory...which is different than CLEARING memory.
The important difference being that the memory stays intact when it gets jettisoned until the OS needs to use it for something else.
Clearing is the same...except you are erasing the contents in addition to freeing the memory up.
When an application is in the background and another application is running and is requiring more memory, can the app in the background receive a memory warning? Or can it only get killed from the memory without any warning?
If it's the latter, should I manually free up memory (cache) in the "applicationDidEnterBackground" method so that there is less chance that it will get killed?
Thank you very much!
Yes, your application can receive a memory warning while in the background. Your application only gets killed immediately if the system really needs the memory, but it'll play nice and ask your application to return memory on its own first. If the system is satisfied it won't kill your application.