I'm working on an iOS app that ideally needs to run the location services in the background. I've tested the significant location, and that isn't accurate enough. The accurate location is perfect, but this consumes far too much battery life to make the app viable.
To get around this battery issue I thought I'd found a solution that uses NSTimer inside UIApplication:beginBackgroundTaskWithExpirationHandler:. This turns the location on and then instantly off again, which triggers a location update and resets the backgroundTimeRemaining.
However, this solution still drains a lot of battery – 15%-20% every 3-4 hours – even when the location is only turned on for one second every 9 minutes. The app is not running anything else in the background aside from this one timer. I've even tried releasing all of the views when entering the background to make sure there is nothing sitting and consuming the battery.
Checking inside instruments, I found the app is using 0.0% of the CPU and 14 MB of memory while in this waiting state. I'm at a bit of a loss at this point as to the cause, especially since running the GPS for 1 second every 540 seconds does not provide an appreciable reduction in battery consumption, compared to running it 24/7.
I've started compiling the following questions, which might contribute to the problem, and I'm hoping somebody has an answer or an idea...
Does running an app in this way stop the phone from entering some sort of low power mode?
Does starting the GPS use huge amounts of power?
Does the GPS keep running for a period of time even after turning off?
Yes, WWDC 2011 Session 312 "iOS Performance and Power Optimization with Instruments" covers this at about the 45 minute mark.
When you finish using the GPS it can remain active for up to 10 seconds, and active radios both wake the device and while active prevent the device from 'sleeping'.
You'll be able to see this using the 'Energy Diagnostics' template in Instruments.
Related
Are these some made up terms? Does cold mean app was killed. And warm means app was in memory?
From docs on Reducing Your App’s Launch Time
For example, on iOS, if you swipe back to the home screen and immediately re-enter the app, that is the fastest activation possible. It’s also likely to be a resume. When the system requires a launch is required, it is commonly referred to as a “warm launch.”
Conversely, if a user just played a memory-intensive game, and they then re-enter your app, for example, it may be significantly slower than your average activation. On iOS, your app typically was evicted from memory to allow the foreground application more memory. Frameworks and daemons that your app depends on to launch might also require re-launching and paging in from disk. This scenario, or a launch immediately after boot, is often referred to as a “cold launch.”
Think of warm and cold launches as a spectrum. In real use, your users will experience a range of performance based on the state of the device. This spectrum is why testing in a variety of conditions is essential to predicting your real world performance.
From WWDC:
So, let's take a look at those launches I talked about before, there's a cold launch, a warm launch, and something is often referred to as launch, but isn't quite a launch, a resume.
Cold launches occur after reboot, or when your app has not been launched for very long time.
In order to launcher app, we need to bring it from disk into memory, startup system-side services that support your app, and then spawn your process.
As you'd expect, this can take a little time, but fortunately, once it's happened once, you'll experience a warm launch. In this case, your app still needs to be spawned, but we've already brought your app into memory and started up some of those system-side services. So, this will be a little bit faster and a little bit more consistent.
Finally, there's that resume. This occurs when a user reenters your app from either the home screen or the app switcher. As you know, the app is already launched at this point, so it's going to be very fast.
What you need to remember from this is not to confuse resumes with launches when you're taking measurements
tldr:
every time you hit the app icon, it can be one of the 4 following states:
app wasn't launched for a long long time or it was just launched after a reboot
app was launched and killed before. But launched again. So some system services are still in memory.
app was launched before, but got suspended to reduce memory, it's process is still ongoing. Hitting the app icon won't trigger an app launch
app was launched, but then only backgrounded. It's still in memory. e.g. you've had app put in background while listening to music or location tracking. So tapping on the app on the app icon, won't trigger another app launch. (this scenario wasn't mentioned in the above docs, but was worth mentioning)
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>)
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?
My app use CPU so it drain battery really quick.
I'm trying to detect what is using CPU with instruments.
I'm running counters and i/o events but can't understand information I recieved. In counters I see only dispatch_mgr_thread at the first place. I'm hiding system libraries and have [UIApplication run] -> method from app in call three.
Is that method the reason of CPU usage?
UPD: I've also checked app with time profiler and here is the result:
And I don't understant what is this "_dispatch_mgr_thread" or "_dispatch_worker_thread3" that works the mostly in my app even while I don't push any bottons - just start app and it does nothing.
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.