Cocoa App使用的内存比它应该多得多

时间:2015-02-18 10:39:16

标签: objective-c json cocoa memory-leaks nsmutablearray

我正在开发一个从API下载和解析大约40k json文件的应用程序。由于我的程序结构,我不会立即解析它们,而是将它们保存在NSMutable数组中。每个json大约1KB,大多数甚至更少。如果我的计算是正确的,那应该会产生大约40MB(+一些开销)的已分配内存。但是当我运行应用程序时,内存使用率攀升至4GB以上。

我在这里泄漏了什么吗?既然我使用垃圾收集,我不需要解除任何东西,对吧?或者我的计算错了?

这是我的代码:

- (void) loadItemsForIds:(NSArray*)idList {

    for (NSNumber* n in idList) {
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://someapi.com/somejson.json?id=%@", n]];
        NSData* response = [NSData dataWithContentsOfURL:url];
        NSDictionary *loadedData = [NSJSONSerialization JSONObjectWithData:response options:0 error:nil];

        @synchronized(self.updateData) {
            [self.updateData addObject:loadedData];
        }

        [self performSelectorOnMainThread:@selector(progressLoadingInterface:) withObject:[loadedData valueForKey:@"name"] waitUntilDone:NO];
    };

}

编辑:

如果我不将数据保存到数组中,则发现问题甚至存在。在经过一些研究之后,我偶然发现了一个处理同样问题的问题:iPhone - Memory Leak - NSData dataWithContentsOfUrl & UIWebView

我的问题可能需要删除。

2 个答案:

答案 0 :(得分:0)

[NSJSONSerialization JSONObjectWithData:response options:0 error:nil]将JSON数据解析为对象。这将占用比1K JSON数据更多的内存。

此外,NSString可能将所有字符串数据存储为unichar,这是一个16位表示:是JSON数据中假设的UTF-8编码大小的两倍。

根据JSON的内容,我可以相信1K的JSON数据可能会成为10K的对象。


但这都是猜测工作。使用Instruments(Product> Profile)检查内存使用情况。这将使您更好地了解哪些对象占用了所有内存。

答案 1 :(得分:0)

你永远不会在40k迭代之间释放内存 =>你永远不会给任何人这样做的机会(arc / gc)

将循环 body 包裹在@autoreleasepool {...}中,以便耗尽内存

for (NSNumber* n in idList) {
    @autoreleasepool {
         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://someapi.com/somejson.json?id=%@", n]];
        NSData* response = [NSData dataWithContentsOfURL:url];
        NSDictionary *loadedData = [NSJSONSerialization JSONObjectWithData:response options:0 error:nil];

        @synchronized(self.updateData) {
            [self.updateData addObject:loadedData];
        }

        [self performSelectorOnMainThread:@selector(progressLoadingInterface:) withObject:[loadedData valueForKey:@"name"] waitUntilDone:NO];
    }
}