I am working on an app which uses iOS NSURLSession background session to upload the data to the S3 server. From iOS 15.x
, We have observed that transfer speed has become too slow (~10 kbps).
Following is the configuration, I am using
- Create the
NSURLSessionConfiguration
using backgroundSessionConfigurationWithIdentifier - Set HTTPMaximumConnectionsPerHost to
8
- Set timeoutIntervalForRequest to
60s
- Set timeoutIntervalForResource to
86400s
(1 Day) - Set discretionary to
false
- Set TLSMinimumSupportedProtocolVersion to
tls_protocol_version_TLSv12
- Create the
NSURLSession
using sessionWithConfiguration - send request using uploadTaskWithRequest
When I tested with iPadOs 14.8.1
, there is no degradation in performance, but with iPadOs 15.3.1
and 15.5
, I can see the performance degradation (uploads getting 6x slow).
When I create the session using ephemeralSessionConfiguration upload is very fast and there is no degradation (working as before).
For all the tests, I am keeping the app in foreground only.
I have few queries:
- Is there any changes in background session configuration for iOS
15.x
and greater ? - We are currently using backgroundSessionConfigurationWithIdentifier to create background sessions. Should we consider moving to background tasks introduced in iOS 13 ?
- Is it upto the OS (in this case
iOS
) to schedule the requests and we (clients) has no or very little control over the transfer speeds ?
PS: The degradation is happening with iOS simulators also.
In case of simulators, somehow it is dependent on macOs versions (as seen from my tests).
On macOs 12.4
, in xCode 13.2
, iOS 12.x
, 13.x
, 14.x
, 15.x
simulators are showing the performance degradation.
When the same app is compiled from macOs 11.4
, xCode 12.4
, iOS 12.x
, 13.x
, 14.x
are not showing any performance degradation.
Any inputs would be highly appreciated.
2
Answers
The simulator likely just passes the requests straight through to NSURLSession on macOS, so it makes sense that the simulator behavior would coincide with the macOS version.
This sounds like a performance regression in macOS 12 and iOS 15. Please file a bug with Feedback Assistant if you haven’t already, and attach a minimum reproducible sample.
Off the top of my head, I can’t think of any reason you’d see a measurable performance difference between an ephemeral and background session unless the out-of-process helper is running at too low a priority.
Background tasks and background downloads are somewhat orthogonal. The former are running in-process in your app, so if your app crashes, they fail. The latter run in a separate process, so they are independent of whether your app is running. Background downloads are more appropriate for large downloads, particularly if your app is large-ish, because it means that iOS can evict your app without terminating the download.
The other obvious question is whether you’re ever starting a task while in the background (e.g. in response to completion of another task). The latter are likely to be throttled, particularly if you start a new transfer after a background upload or download finishes. You can avoid that penalty by combining resources and uploading them in a single blob (e.g. a zip file). I’m assuming from your question that you are not, but I just wanted to be certain. 🙂
I’m also assuming that this is either over Wi-Fi or is network-agnostic, given that you also see it on macOS.
Finally, I’m assuming that this isn’t an HTTP/3 (QUIC) issue. That is, of course, the biggest change in NSURLSession in iOS 15 and macOS 12, so if I were pointing fingers, that would be my first suspect.
I have no knowledge one way or the other, but I could easily see Apple decide to disable that feature for ephemeral sessions, because it may or may not be trivial to avoid storing cookies, etc. when you are reusing connections and making multiple requests in parallel.
If that’s the issue, you might see if there’s some way to disable that feature either on the server end or the client end. I don’t know of a way to do so off the top of my head, though.
Having struggled with this problem myself, I wanted to share the solution – for others, and also for future me when I run into this again and inevitably forget: to fix slow download speeds for uploads using a background session configuration, make sure you configure the request’s network service type – this setting works for me:
.responsiveAV
also worked for me. Do make sure you are only setting this if it is important that uploads happen in a timely manner – if it isn’t important just hand it off to the background session with an appropriately configured timeout and let it get on with it.Note: this will only have an impact if the upload task is started while the app in the foreground. If the upload task begins when the app is already in the background (for example, you need to do some other work first with some extended background execution time and then resume the upload task) then it will ignore this and behave as if you had set it to
.background
which will be as slow as before as requests started in the background are heavily throttled.