【问题标题】:Excessive memory footprint when storing JSON (as NSData) on Core Data Object via ARC in Core Data通过核心数据中的 ARC 在核心数据对象上存储 JSON(作为 NSData)时内存占用过多
【发布时间】:2014-01-15 21:56:20
【问题描述】:

我正在将数百 MB 文件集加载到 Core Data 中。我没有使用关系连接,而是发现通过创建 NSDictionaries / NSArray 并将它们序列化到核心数据记录上,我可以获得更好的性能。到目前为止的问题是我的内存占用空间由于 ot 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 - 你会如何建议我将对象嵌入核心数据(或者你建议)? 2 - 是否有更好的 JSON 序列化库可以提供更低的内存占用? 3 - 我应该放弃 ARC 吗?如果是,怎么办? 4 - 还有其他建议吗?使用单独的导入“应用程序”将是一种可能的替代临时解决方案,但不是我愿意长期在 App-Store 上看到的东西。

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

【问题讨论】:

  • 使用@autoreleasepool
  • 是的,在 dataWithJSONObject 调用周围放置一个自动释放池。 (假设 stackData 是“强”。)

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


【解决方案1】:

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

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

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

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

【讨论】:

  • 抱歉,回复很长(感谢您的快速回复!)。不得不处理 [stackoverflow.com/questions/17477263/… |这] 首先。这将内存从几 GB 降低到 1 GB 以下,甚至没有注释所有代码。谢谢!
  • 不用担心,很高兴它有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多