核心数据导入 – 不释放内存

我的问题是关于核心数据和内存不被释放。 我正在做一个同步过程从一个返回一个JSON的WebService导入数据。 我在内存中加载要导入的数据,循环并创buildNSManagedObjects。 导入的数据需要创build与其他对象有关系的对象,总共有11.000个左右。 但是为了隔离这个问题,我现在只创build第一层和第二层的项目,把这个关系留下来,这些是9043个对象。

我开始检查使用的内存量,因为应用程序在进程结束时崩溃(使用完整的数据集)。 第一次内存检查是在内存中加载json之后,以便测量真的只考虑创build,并将对象插入到核心数据中。 我用来检查使用的内存是这个代码( 源 )

 - (void)get_free_memory {

     struct task_basic_info info;
     mach_msg_type_number_t size = sizeof(info);
     kern_return_t kerr = task_info(mach_task_self(), 
                                    TASK_BASIC_INFO,
                                    (task_info_t)信息,
                                    &尺寸);
    如果(kerr == KERN_SUCCESS){
         NSLog(@“Memory in use(in bytes):%f”,(float)(info.resident_size / 1024.0)/1024.0);
     } else {
         NSLog(@“Error with task_info():%s”,mach_error_string(kerr));
     }
 }

我的设置:

  • 1个持久店铺协调员
  • 1 Main ManagedObjectContext(MMC)(NSMainQueueConcurrencyType用于读取(只读)应用程序中的数据)
  • 1后台ManagedObjectContext(BMC)(NSPrivateQueueConcurrencyType,undoManager设置为nil,用于导入数据)

BMC独立于MMC,所以BMC不是MMC的子环境。 而且他们不共享任何家长的上下文。 我不需要BMC通知MMC的更改。 所以BMC只需要创build/更新/删除数据。

者平台:

  • iPad 2和3
  • iOS,我已经testing过将部署目标设置为5.1和6.1。 没有区别
  • XCode 4.6.2

问题:导入数据后,使用的内存不会停止增加,即使在进程结束后,iOS似乎也无法消耗内存。 其中,如果数据样本增加,导致内存警告,并在应用程序closures后。

研究:

  1. 苹果文档

    • 有效地导入数据
    • 减less内存开销
  2. 将数据导入到核心数据时需要牢记的几点( Stackoverflow )

  3. testing完成并分析内存释放。 他似乎和我有同样的问题,他发了一个苹果报告,苹果没有回应。 ( 来源 )

  4. 导入和显示大型数据集( Source )

  5. 指示导入大量数据的最佳方法。 虽然他提到:

    “我可以在稳定的3MB内存中导入数百万条logging,而不需要调用”reset“。

    这让我觉得这可能有点可能吗? ( 来源 )

testing:

数据示例:共创build9043个对象。

  • closures创build关系,因为文件说他们是“昂贵的”
  • 没有提取正在完成

码:

- (void)processItems { [self.context performBlock:^{ for (int i=0; i < [self.downloadedRecords count];) { @autoreleasepool { [self get_free_memory]; // prints current memory used for (NSUInteger j = 0; j < batchSize && i < [self.downloadedRecords count]; j++, i++) { NSDictionary *record = [self.downloadedRecords objectAtIndex:i]; Item *item=[self createItem]; objectsCount++; // fills in the item object with data from the record, no relationship creation is happening [self updateItem:item WithRecord:record]; // creates the subitems, fills them in with data from record, relationship creation is turned off [self processSubitemsWithItem:item AndRecord:record]; } // Context save is done before draining the autoreleasepool, as specified in research 5) [self.context save:nil]; // Faulting all the created items for (NSManagedObject *object in [self.context registeredObjects]) { [self.context refreshObject:object mergeChanges:NO]; } // Double tap the previous action by reseting the context [self.context reset]; } } }]; [self check_memory];// performs a repeated selector to [self get_free_memory] to view the memory after the sync } 

Measurment:

它从16.97 MB到30 MB,在同步后下降到28 MB。 每5秒重复一次get_memory调用,将内存保持在28 MB。

其他testing没有任何运气:

  • 如研究2)所示重新创build持久存储没有效果
  • testing让线程稍等一会,看内存是否恢复,例4)
  • 在整个过程之后将环境设置为零
  • 在整个过程中不保存上下文(丢失信息)。 实际上,结果是维持较less的内存量,使其保持在20 MB。 但它仍然不会减less,我需要的信息存储:)

也许我失去了一些东西,但我真的testing了很多,并遵循指导方针,我期望看到内存再次下降。 我运行Allocations工具来检查堆的增长,这似乎也很好。 也没有内存泄漏。

我正在用尽想法来testing/调整…如果有人能帮助我了解我还能testing什么,或者指出我做错了什么,我将不胜感激。 或者就是这样,它应该如何工作……我怀疑…

谢谢你的帮助。

编辑

我已经使用工具来分析活动监视器模板的内存使用情况,“Real Memory Usage”中显示的结果与使用get_free_memory打印在控制台中的结果get_free_memory ,并且内存似乎永远不会被释放。

好吧,这是相当尴尬的…僵尸已启用的计划上,他们被closures的参数,但在诊断“启用僵尸对象”被检查…

closures此function可以保持内存的稳定。

感谢那些读过这个问题的人,并试图解决它!

在我看来,你最喜欢的源代码(“3MB,数百万条logging”)的关键就是提及的批处理 – 除了禁用苹果公司推荐的撤销pipe理器,也非常重要)。

我认为这里重要的是这个批处理也必须适用于@autoreleasepool

每1000次迭代就不足以排空自动释放池。 您需要实际保存MOC,然后排空游泳池。

在你的代码中,尝试把第二个@autoreleasepool放到第二个for循环中。 然后调整您的批量大小以进行微调。

我在原版iPad 1上做了超过500.000条logging的testing.JSONstring的大小接近40MB。 尽pipe如此,这一切都没有崩溃,一些调整,甚至导致可以接受的速度。 在我的testing中,我可以声称应用程序。 原始iPad上有70MB的内存。