我正在解析一个大约53 MB的iPad上的JSON文件。解析工作正常,我正在使用Yajlparser这是一个SAX解析器,并设置如下:
NSData *data = [NSData dataWithContentsOfFile:path options:NSDataReadingMappedAlways|NSDataReadingUncached error:&parseError];
YAJLParser *parser = [[YAJLParser alloc] init];
parser.delegate = self;
[parser parse:data];
到目前为止一切正常,但JSON文件变大了,现在我突然在iPad 2上遇到内存警告。它收到4个内存警告,然后崩溃。在iPad 3上,它可以完美运行,没有任何内存警告。
我已经开始使用Instruments进行分析并发现了很多CFNumber分配(我已经在几分钟之后停止了仪器,我之前运行它直到崩溃并且CFNumber事件大约为60 mb或更多)。
打开CFNumber详细信息后,它显示了一个巨大的分配列表。其中一个向我展示了以下内容:
另一个在这里:
那么我做错了什么?那个数字(例如最后一张图片中的72.8%)代表什么?我正在使用ARC,所以我没有做任何发布或保留等等。
感谢您的帮助。 干杯
编辑:我已经在这里询问了如何解析这些大文件的问题:iPad - Parsing an extremely huge json - File (between 50 and 100 mb)
所以解析本身似乎没问题。
答案 0 :(得分:5)
请参阅Efficiently Importing Data上的Apple核心数据文档,特别是“减少峰值内存占用”。
您需要确保一次在内存中没有太多新实体,这包括在解析数据时定期保存和重置上下文,以及使用自动释放池。
一般的sudo代码是这样的:
while (there is new data) {
@autoreleasepool {
importAnItem();
if (we have imported more than 100 items) {
[context save:...];
[context reset];
}
}
}
所以基本上,在主循环周围放置一个自动释放池或解析代码。计算已创建的NSManagedObject
个实例数,并定期保存并重置托管对象上下文以刷新这些内存不足。这应该可以减少你的内存占用。数字100
是任意的,您可能希望尝试使用不同的值。
因为您要保存每个批次的上下文,所以您可能希望导入商店的临时副本,以防出现问题并让您进行部分导入。一切都完成后,您可以覆盖原始商店。
答案 1 :(得分:1)
尝试在执行一定量的插入操作后使用[self.managedObjectContext refreshObject:obj refreshChanges:NO]
。这会将NSManagedObjects变成错误并释放一些内存。