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

标签 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

最佳答案

尝试使用@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);
        }
    });
}

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

if your block creates more than a few Objective-C objects, you might want to enclose parts of your block’s code in an @autorelease block to handle the memory management for those objects. Although GCD dispatch queues have their own autorelease pools, they make no guarantees as to when those pools are drained. If your application is memory constrained, creating your own autorelease pool allows you to free up the memory for autoreleased objects at more regular intervals

关于ios - GrandCentralDispatch 大下载队列最终耗尽内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22923523/

相关文章:

java - 按顺序并发运行 Runnable

html - Safari CSS 字体颜色问题

iOS/iPhone - 快速拍摄或连拍照片

objective-c - 当 AfterdidCompleteWithError 调用时,如何使用 URLSession downloadTaskWithResumeData 再次开始下载..?

objective-c - 在 TabBar 控制的 iOS 应用程序中的第二个选项卡中进行交互时,将 RemoteControlEvents 接收到第一个选项卡

javascript - 在内部动画完成之前不要执行函数

iOS UITableView 单元格

ios - MultipeerConnectivity 在 iOS 14 上无法按预期工作

ios - HKHealthStore.isHealthDataAvailable 的目的是什么?

java - 在Java并发教程的fork/join部分中, "computeDirectly"函数是如何通过 "invokeAll"执行的?