iOS process throttling from push/backgroundFetch

In my iOS app, I am using a serial DispatchQueue and create a background task to do some work. If this process is initiated while the app is in the foreground, it is very fast and efficient. Depending on the age of the device, the job takes from 4.5 - 12.2 seconds.


The app also utilizes backgroundFetch and content-available silent pushes to do this work in the background so that the user stays updated. The thing I'm struggling with is that iOS seems to be severely throttling the performance of the work being done, and it's worse on newer iPhone models -- it's up to 9X slower. In the background initiated case, the OS limits the time you have to complete this work (~30 seconds), which makes it impossible to complete in a single pass.


Unfortunately, the work involves some failry intensive I/O (either reading from a DB or file, both take about the same amount of time), and it doesn't lend itself to easily splitting the work into multiple passes.


Here are some examples of processing times:


iPhone SE

12.2 sec FG -> 23.3 sec BG (1.9X slower)


iPhone 7

9.0 sec FG -> 21.2 sec BG (2.3X slower)


iPhone 8

7.3 sec FG -> 61.2 sec BG (8.3X slower)


iPhone XS

4.5 sec FG -> 40.5 sec BG (9.0X slower)


I understand why the process might be slightly slower in the background, but does anyone know why is it so extreme on newer devices?


I've tried everything I can think of to increase the speed (including setting a higher priority on the DispatchQueue) to no avail. Is there a way to avoid the throttling? If not is there a reliable way to extend the process time in order to finish the processing?


Any other suggestions would be welcome.

Replies

it's worse on newer iPhone models

Keep in mind that newer devices have much faster CPUs, which consume more energy at full speed, so the total energy budget might be the same across models. And this matters because the energy use is what affects standby battery life.

Is there a way to avoid the throttling?

Nothing springs to mind, but I don’t know enough about the specifics of this to give you a definitive answer.

If not is there a reliable way to extend the process time in order to finish the processing?

The only way to extend background execution time is via a

UIApplication
background task [1]. See my UIApplication Background Task Notes post for details. You should be able to get about 30 seconds using this API, which sounds like it’s enough to complete your task.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] And the related

NSProcessInfo
API.