使用 NSURLSession 在后台上传文件时无法保持恒定速度 [英] Unable to sustain a Constant Speed while Uploading files in the background with NSURLSession

查看:41
本文介绍了使用 NSURLSession 在后台上传文件时无法保持恒定速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 AFURLSessionManager 在后台将大约 100 张图像以 10 个小批量的形式上传到 S3,就像这里所做的一样 - 管理后台NSURLSession中活动任务的数量

I am trying to upload some 100 images to S3 in the background with AFURLSessionManager in small batches of 10 like what is being done here- Manage the number of active tasks in a background NSURLSession

我正在使用共享的 NSURLSession 并在完成某些任务时根据更多任务添加任务.每个文件的平均大小约为 1.6 MB,每个任务队列保证运行的任务数为 5

I am using a shared NSURLSession and adding tasks according more tasks to this when some tasks are completed. Average size of each file is about 1.6 MB and the number of tasks that are guaranteed to run per a task queue is 5

这是我添加任务的方法:(也可作为更易于阅读的gist)

Here is my method for adding the tasks: (also available as an easier-to-read gist)

    - (void) addTasksToSessionWithTaskObject:(Task*)taskObject withSessionInitialisationNeeded:(BOOL) needed{

        NSString *filePath = [[NSBundle mainBundle] pathForResource:pathForResourceFile ofType:resourceFileType];
        S3PutObjectRequest *putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:targetFileKey
                                                                              inBucket:_bucketname];
        putObjectRequest.cannedACL = [S3CannedACL publicReadWrite];
        putObjectRequest.filename = filePath;
        putObjectRequest.contentType = [resourceFileType isEqualToString:@"MOV"] ? @"movie/mov" : @"image/jpg";
        putObjectRequest.endpoint = @"http://s3.amazonaws.com";
        putObjectRequest.contentLength=[[[NSFileManager defaultManager]
                                         attributesOfItemAtPath:filePath error:nil] fileSize];
        putObjectRequest.delegate = self;
        [putObjectRequest configureURLRequest];
        NSMutableURLRequest *request = [s3Client signS3Request:putObjectRequest];
        NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://s3.amazonaws.com/UploadTest/%@",taskObject.fileKey]]];

        [request2 setHTTPMethod:request.HTTPMethod];
        [request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]];

        if(needed) {

                sharedSession = [self backgroundSession];   
        }
   NSURLSessionUploadTask *task = [sharedSession uploadTaskWithRequest:request2           fromFile:forFileUrl];

    task.taskDescription = pathForResourceFile;
    [currentlyActiveTaskIdArray addObject:@([task taskIdentifier])];

    [task resume];
}

这就是我对委托所做的

- (void)URLSession:(NSURLSession *)sessionI task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error{

    dispatch_async(dispatch_get_main_queue(), ^{

        __block UIBackgroundTaskIdentifier bgTaskI = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
        }];

        if([currentlyActiveTaskIdArray containsObject:@([task taskIdentifier])]){
            [currentlyActiveTaskIdArray removeObject:@([task taskIdentifier])];
        }
        if(currentlyActiveTaskIdArray.count < LOWER_SLAB_FOR_TASKS + 1){   
            [self initiateS3UploadForSetOfTasksIsItBeginningOfUpload:NO];
        }
        [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
    }); 
}

这是添加更多任务的代码

Here is the Code to add more tasks

 - (void) initiateS3UploadForSetOfTasksIsItBeginningOfUpload:(BOOL)beginning{
        int i=0;
        for(Task *eachTaskObject in tasksArray){
            if(i < numberOfTasksTobeAdded){  
                [self addTasksToSessionWithTaskObject:eachTaskObject WithSessionInitialisationNeeded:NO];
                i++;
            }
        }
    }

我一直在以前台模式和后台模式运行 100 个文件的测试.在前台模式下,它以一致、稳定和恒定的速度上传文件,在前 3 分钟内完成 90 个文件,在 20 秒内完成剩余的 10 个文件.

I've been running tests with 100 files in Foreground mode and Background mode. In Foreground mode, it uploads the files at a consistant, steady and constant speed, it completes 90 files in the first 3 minutes, and the remaining 10 files in 20 seconds.

当我在后台模式下运行应用程序时,我希望它能像在 3 分钟前台窗口中一样快地上传前 90 个文件,然后放慢速度……但事实并非如此.在后台模式下,它在第一分钟上传 15 个文件,然后它开始变慢......很多.它开始以越来越慢的间隔分批上传 8 个文件:1 分钟、3 分钟、5 分钟、10 分钟,现在是 17 分钟.我们在 46 分钟内处理了 65 个文件.

When I run the app in Background mode, I would expect it to upload the first 90 files just as fast as it did in the 3 minute Foreground window, and then slow down after that... but that's not the case. In Background mode, it uploads 15 files in the first minute, then it starts slowing down... a lot. It starts uploading in 8 file batches in slower and slower intervals: 1 minute, 3 minutes, 5 minutes, 10 minutes, and now 17 minutes. We're at 65 files 46 minutes in.

有没有办法让它至少保持前三分钟的速度,或者在后台保持一致的速度?

Is there a way to either keep it fast for at least the fist 3 minutes, or keep consistent speed in the background?

更新: 根据这里 Clay 的评论,我从 AFURLSessionManager 切换回 NSURLSession,因为正如他指出的那样,使用基于块的回调对于 NSURLSession 来说是一项极具风险的业务.此外,我使用了 HTTPMaximumConnectionsPerHost 并将其设置为 10 左右 - 这提供了更好的结果,但离我想要的还差得很远.

UPDATE: Following the comments from Clay here Ive switched back to NSURLSession from AFURLSessionManager because as he points out using block based callbacks is an extremely risky business with NSURLSession. Further I've played with HTTPMaximumConnectionsPerHost and set this around 10-this has given better results but nowhere near what I would want to be.

推荐答案

据我所知,setTaskDidCompleteBlock: 不是 Apple API,NSURLSession 相关的方法.它一个AFURLSessionManager方法(文档).如果您在这方面使用 AFNetworking,那么您需要声明 粗体、顶部、前端和中间.这与使用 NSURLSession 完全不同..我猜 AFNetworking 基于 NSURLSession 的背景实现有其自身的弱点和特质.

From what I can tell, setTaskDidCompleteBlock: is not an Apple API, NSURLSession-associated method. It is an AFURLSessionManager method (docs). If you are using AFNetworking on this, then you need to be announcing that bold, top, front and center. That is not the same, at all, as using NSURLSession. I would guess AFNetworking's background NSURLSession-based implementation comes with its own foibles and idiosyncrasies.

就我而言,无论我在持续后台 NSURLSession 上传方面取得的任何成功都只使用了股票 API.

For my part, whatever success I've had with sustained background NSURLSession uploads are using only the stock API.

  • 关于 AFNetworking:我们将它用于一般的 web api I/O.在 NSURLSession 出现的时候,AFNetworking 确实没有强大的支持 app-in-background ops,所以我没有使用它.可能是因为我经历了后台NSURLSession痛苦&欺侮,我在现在你有两个问题"的标题下斜视AFNetworking背景.但也许他们现在已经破解了坚果.

  • Regarding AFNetworking: we use it for general web api I/O. At the time NSURLSession came out, AFNetworking really didn't robustly support app-in-background ops, so I didn't use it. Perhaps because I went through the background NSURLSession pain & hazing, I look askance at AFNetworking backgrounding under the rubric of "Now you have two problems". But maybe they have cracked the nut by now.

  • 我争取一个 NSURLSession.我开始对创作和创作不屑一顾.会话的破坏,但发现这会导致一些真正棘手的问题.对此,经验似乎各不相同.

  • I strive for one NSURLSession. I started out being cavalier about creation & destruction of sessions, but found this made for some truly gnarly problems. Experiences seem to vary on this.

我使用默认的 HTTPMaximumConnectionsPerHost,没有问题.Apple 文档对默认值保持沉默,但这是 lldb 在我选择的随机特定设备/操作系统中告诉我的:
<代码>(lldb) p [配置 HTTPMaximumConnectionsPerHost](NSInteger) $0 = 4
如果您在后台速度变慢方面遇到问题,我怀疑调整这是否在正确的轨道上.

I use the default HTTPMaximumConnectionsPerHost, no problems there. The Apple docs are silent on the default value, but here's what lldb tells me in the random particular device/OS I chose:
(lldb) p [config HTTPMaximumConnectionsPerHost] (NSInteger) $0 = 4
If you are having troubles with backgrounding slowing down, I doubt tweaking this is on the right track.

FWIW,后台NSURLSession不支持块接口,仅委托.

FWIW, background NSURLSessions do not support the block interfaces, delegate only.

这篇关于使用 NSURLSession 在后台上传文件时无法保持恒定速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆