在核心数据中通过ARC在核心数据对象上存储JSON(作为NSData)时,内存占用空间过大

时间:2014-01-15 21:56:20

标签: objective-c json core-data automatic-ref-counting nsdata

我正在将数百MB的文件集加载到Core Data中。我没有使用关系连接,而是发现通过创建NSDictionaries / NSArray并将它们序列化到Core Data记录中,我获得了更好的性能。到目前为止的问题是,由于malloc归因于这条线路,我的记忆足迹已经通过屋顶:

NSMutableDictionary *stackEntryDictionary = [NSMutableDictionary dictionary];
NSDictionary *stackDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSString stringWithUTF8String:parts[6].c_str()], @"relationship"
                                , [NSString stringWithUTF8String:parts[8].c_str()], @"sequenceId"
                                , [NSString stringWithUTF8String:parts[9].c_str()], @"sequence"
                                , [NSString stringWithUTF8String:parts[7].c_str()], @"block"
                                , [NSNumber numberWithInteger:row], @"entryId"

                                , nil ];
if ([relationship isEqualToString:@"consensus"] || [relationship isEqualToString:@"model"]) {
                            [stackEntryDictionary setObject:stackDictionary forKey:relationship];
                            row = 1;
                        }
                        else {
                            [stackEntryDictionary setObject:stackDictionary forKey:[NSNumber numberWithInt:row].stringValue];
                            ++row;

                        }


stackEntryDatumMO = [NSEntityDescription insertNewObjectForEntityForName:@"StackEntryDatum" inManagedObjectContext:document.managedObjectContext];
stackEntryDatumMO.sampleId = sampleMO.sampleId;
stackEntryDatumMO.name = sampleMO.name;

stackEntryDatumMO.tagId = [NSNumber numberWithInteger:locusId];

// THIS IS THE "BAD LINE" that issues a lot of NSString malloc's 

stackEntryDatumMO.stackData = [NSJSONSerialization dataWithJSONObject:stackEntryDictionary options:0 error:&error];

当我完全退出循环时(每个文件大约70K,30个文件,插入字典的平均大小大约为20),这会被清除。但是,我正在使用大约10 GB的内存来杀死应用程序性能并且是不必要的。

所以,我有两个问题: 1 - 您如何建议我将对象嵌入Core Data(或者您建议)? 2 - 是否有更好的JSON序列化库可以提供更低的内存占用量? 3 - 我应该放弃ARC吗?如果是这样的话? 4 - 还有其他建议吗?使用单独的导入“应用程序”将是一种可能的替代临时解决方案,但不是我愿意看到的长期在App-Store上发布的内容。

我还应该提一下,当ARC在加载后清理时,它会在尝试释放已经释放的对象时终止应用程序(如果需要可以稍后发布错误)。这不会发生在较小的文件上。

1 个答案:

答案 0 :(得分:1)

尝试在@autoreleasepool中包装NSJSONSerialization调用,它会在调用后创建大量自动释放的对象。

至于你正在做什么,将它们存储为NSData将在CoreData中产生与将它们存储在自己的文件中相同的内存占用量。对于NSManagedObject所需的东西,你需要为每个对象支付更多,但净成本大致相同。

您可以通过强制CoreData对象更频繁地解除分配来调整占用空间,最突然的方法是保存然后释放您正在使用的托管对象上下文。必要时应用@autoreleasepool。

如果您可以在循环中发布Instruments分配工具的样本,或者堆的快照,也会有所帮助。