4

I am working on an app that uploads images to a server, and I am using background NSURLSessionUploadTasks. This works perfectly for small numbers of uploaded images, such as 10 to 20 photos. However, I have been running into problems when trying to upload 100+ images at once. How scalable are background NSURLSessionUploadTasks?

When I call

NSURLSessionUploadTask *task = [uploadSession uploadTaskWithRequest:request fromFile:fileURL];

repeatedly, it blocks waiting for a semaphore. Is this due to the round trip time communicating with the background upload daemon? Is it waiting for the background upload daemon to process the other upload tasks? With over 100 photos, I have seen these calls block for a total of over 40 seconds. Also, once these calls finish, it takes a while for uploads to make any progress, and they frequently stall for many seconds at a time.

I would love to be able to set up my 100+ upload tasks and sit back and let iOS 7 handle the uploads for me. However, if I have to, I can create the upload tasks just a few at a time. That seems like a shame with such an advanced background upload feature available in iOS 7. I might as well be using NSURLConnection under iOS 6.

Thanks for your help.

Ekra
  • 3,241
  • 10
  • 41
  • 61
landweber
  • 2,313
  • 1
  • 19
  • 12

3 Answers3

1

NSURLSession is a refactored and enhanced NSURLConnection, not a magic tool. What I do when using it is throttle the outstanding transactions at a fixed max like 4 or 10. I do this now after a long exchange with Quinn on Apples private dev forums (I can probably dig up a link if interested). In the end, his point was that Apple cannot really do the throttling for you, you need to actively manage the number. So yes, in this regard there is not a lot of difference between 6 and 7.

Using a max of 4 connections, I have no problem getting hundreds of images at a time.

David H
  • 40,852
  • 12
  • 92
  • 138
  • I would be interested in a link @David if you can find it. – Glen T Dec 18 '13 at 00:30
  • I read that exchange with Quinn, and I had my own exchange with him back in October. The problem is that you cannot manage the number of active tasks when they are running in the background. The app is not woken up regularly enough when it is in the background to initiate new tasks. It appears that NSURLSession is designed to complete only a small number of tasks in the background, and does not scale well. And if Apple knows that it does not scale well, that should be documented. As for throttling, you can limit the number of concurrent connections. – landweber Apr 03 '14 at 04:30
  • A workaround might be to glom all images into one huge file, transfer that one file in a background task. – David H Apr 03 '14 at 11:22
  • 1
    @landweber I created an auto-answered question to possibly address what you are talking about, here: http://stackoverflow.com/questions/22840115. Using that technique, I've been able to keep my upload queue full for some time, enough to upload say 1000 items. – Clay Bridges Apr 03 '14 at 14:20
1

FYI, I reported the surprising delay in

NSURLSessionUploadTask *task = [uploadSession uploadTaskWithRequest:request fromFile:fileURL];

as a bug to Apple and learned that it is a known and still open bug in iOS.

To work around this problem, I now create the NSURLSessionUploadTask in a separate thread. To avoid overwhelming the nsnetworkd background daemon, I limit it to 300 tasks at a time, which works fine.

landweber
  • 2,313
  • 1
  • 19
  • 12
  • I do this as well so it is a technique that works. Background uploading, FYI, is going to be slow though. – P. Ent Oct 31 '22 at 19:39
0

I have couple of clarifying questions, and I apologize, but they don't fit well in the comment format.

  1. Are you creating a session using a configuration created with
    -[NSURLSessionConfiguration backgroundSessionConfiguration:]?

  2. Are your uploads occurring when your app is not in the foreground, e.g. suspended?

Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
  • Clay, sort of a side question. Have you had success using backgroundSessionConfiguration: with NSURLSessionUploadTask? Right now it keeps crashing my app at uploadTaskWithRequest: and it's crushing me :( – Dinkman123 Feb 13 '14 at 21:37
  • Yes, I am using a backgroundSessionConfiguration, and yes, these uploads are occurring when the app is in the background. – landweber Apr 03 '14 at 04:26
  • @Dinkman123 Like landweber, I'm having success. There are a lot of landmines though. E.g. I wouldn't be willy-nilly about creating sessions with new unique sessionIds, because it seems if you lose track of these, they can gum up the works by remaining on disk "forever". Are you setting a session delegate? – Clay Bridges Apr 03 '14 at 13:57
  • Hey Clay, I'm probably gumming up the works, as I'm generating random ID's for each session and casting them off into the abyss. Not clear what the actual cost of that is in the real world, so far it doesn't seem to have bitten me or any of the other users. I added a code sample in this post (not the one in the original question, scroll down for the working one): http://stackoverflow.com/questions/21767334/uploads-using-backgroundsessionconfiguration-and-nsurlsessionuploadtask-cause-ap/21767905#21767905 – Dinkman123 Apr 03 '14 at 21:42