5

我正在解析一个大约 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 分配(几分钟后我停止了 Instruments,我让它在崩溃之前运行,并且 CFNumber 的东西大约是 60 mb 或更多)。

CFNumber 分配

打开 CFNumber 详细信息后,它显示了一个巨大的分配列表。其中一个向我展示了以下内容:

CFNumber 分配 1

还有一个在这里:

CFNumber 分配 2

那么我做错了什么?这个数字(例如最后一张图片中的 72.8%)代表什么?我正在使用 ARC,所以我没有做任何 Release 或 Retain 或其他任何事情。

谢谢你的帮助。干杯

编辑:我已经问过如何在这里解析如此大的文件的问题:iPad - Parsing anextreme huge json - File ( between 50 and 100 mb)
所以解析本身似乎很好。

4

2 回答 2

5

请参阅 Apple 关于Efficiently Importing Data的 Core Data 文档,尤其是“Reducing Peak Memory Footprint”。

您需要确保一次在内存中没有太多新实体,这涉及在解析数据时定期保存和重置上下文,以及使用好自动释放池。

一般的 sudo 代码是这样的:

while (there is new data) {
    @autoreleasepool {
        importAnItem();
        if (we have imported more than 100 items) {
            [context save:...];
            [context reset];
        }
    }
}

所以基本上,在你的主循环或解析代码周围放置一个自动释放池。计算您创建了多少NSManagedObject实例,并定期保存和重置托管对象上下文以将这些实例从内存中清除。这应该可以减少您的内存占用。该数字100是任意的,您可能想尝试不同的值。

因为您要保存每个批次的上下文,所以您可能希望导入商店的临时副本,以防出现问题并留下部分导入。一切都完成后,您可以覆盖原始存储。

于 2013-08-27T13:23:13.477 回答
1

尝试[self.managedObjectContext refreshObject:obj refreshChanges:NO]在一定数量的插入操作后使用。这会将 NSManagedObjects 变成故障并释放一些内存。

Apple Docs 关于提供的方法

于 2013-08-27T21:16:32.023 回答