无法维持恒定的速度,而在与NSURLSession后台上传文件在与、上传文件、后台、速度

2023-09-11 08:22:04 作者:面具后的冷笑

我想上传一些100的图像S3与AFURLSessionManager在10小批量背景像正在做什么,这里 - Manage活动任务在后台数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

下面是我的方法添加的任务: (也可作为一个更容易阅读要点)

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];
}

这是我的代表做了

And this what I've done with the delegate

- (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];
    }); 
}

下面是code,以增加更多的任务

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.

当我运行在后台模式下的应用程序,我希望它上传第一个90个文件一样快,因为它在3分钟前台窗口那样,并在那之后减慢......但事实并非如此。在后台模式下,它上传在第一分钟15个文件,然后开始放缓...很多。它开始上载在8文件分批慢间隔:1分钟,3分钟,5分钟,10分钟,现在17分钟。我们在65个文件46分钟研究。

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.

有没有一种方法来保持快速,至少拳头3分钟,或保持速度一致的背景是什么?

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

更新:继克莱香港专业教育学院切换回NSURLSession从AFURLSessionManager的意见在这里,因为正如他所指出的使用基于块的回调是一个非常冒险的事与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:不是苹果的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真的没有有力支持应用功能于后台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 ,有没有问题。苹果文档是沉默的默认值,但这里是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.