GrandCentralDispatch大下载队列最终耗尽内存

时间:2014-04-07 21:32:12

标签: ios objective-c concurrency grand-central-dispatch

我目前的代码是为我们的企业应用程序提供一个大的文件列表(大约6k图像,大小约为2.8GB)。

在大约1.71GB传输文件(~660秒)时,内存显然已耗尽。我想知道我可以做些什么来优化:

队列:

dispatch_queue_t imageQueue1 = dispatch_queue_create("Image Queue 1", NULL);

循环:

for (int i = 0; i < [imgs count]; i++) {
    dispatch_async(imageQueue1, ^{
        NSString *path = [[NSString alloc] initWithFormat:@"%@/%@", damPath, [imgs objectAtIndex:i]];
        NSURL *url = [[NSURL alloc] initWithString:path];
        NSData *data = [[NSData alloc] initWithContentsOfURL:url];

        NSString *savePath = [[NSString alloc] initWithFormat:@"%@/%@", newDir, [imgs objectAtIndex:i]];

        if (![data writeToFile:savePath atomically:YES]) {
            NSLog(@"Saving of \"%@\" failed!", [imgs objectAtIndex:i]);
        }

        NSString *progress = [[NSString alloc] initWithFormat:@"%d / %u downloaded...", i, [imgs count]];
        NSLog(@"%@", progress);
    });
}

我也想知道如何对这些GCD队列进行多任务处理。对于我的测试,我只是将此代码复制粘贴了6次,其中imageQueue#递增而[imgs count]是固定偏移量,仅用于测试目的。

更新

帽子以颚状图案运行到约38~MB的帽子:

enter image description here

1 个答案:

答案 0 :(得分:1)

尝试使用@autoreleasepool为自动释放的内存提供消耗的机会:

for (int i = 0; i < [imgs count]; i++) {
    dispatch_async(imageQueue1, ^{
        @autoreleasepool {
            NSString *path = [[NSString alloc] initWithFormat:@"%@/%@", damPath, [imgs objectAtIndex:i]];
            NSURL *url = [[NSURL alloc] initWithString:path];
            NSData *data = [[NSData alloc] initWithContentsOfURL:url];

            NSString *savePath = [[NSString alloc] initWithFormat:@"%@/%@", newDir, [imgs objectAtIndex:i]];

            if (![data writeToFile:savePath atomically:YES]) {
                NSLog(@"Saving of \"%@\" failed!", [imgs objectAtIndex:i]);
            }

            NSString *progress = [[NSString alloc] initWithFormat:@"%d / %u downloaded...", i, [imgs count]];
            NSLog(@"%@", progress);
        }
    });
}

查看文档,调度队列确实提供自动释放池,但不能保证它们会被耗尽,因此对于像这样的内存密集型操作,您可能通过添加自己的操作很好地服务

  

如果您的块创建了多个Objective-C对象,您可能希望将块的代码部分包含在@autorelease块中,以处理这些对象的内存管理。尽管GCD调度队列具有自己的自动释放池,但它们无法保证这些池何时耗尽。如果您的应用程序受内存限制,则创建自己的自动释放池可让您以更加固定的时间间隔释放自动释放对象的内存