核心数据导入 - 不释放内存 [英] Core Data Import - Not releasing memory

查看:151
本文介绍了核心数据导入 - 不释放内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是关于Core Data和内存未被释放。我正在做一个同步过程从WebService导入数据,返回一个json。我加载,在内存中,要导入的数据,循环并创建NSManagedObjects。导入的数据需要创建与其他对象具有关系的对象,总共有大约11.000。但是为了隔离问题,我现在只创建第一和第二级的项目,留下的关系,那是9043对象。

My question is about Core Data and memory not being released. I am doing a sync process importing data from a WebService which returns a json. I load in, in memory, the data to import, loop through and create NSManagedObjects. The imported data needs to create objects that have relationships to other objects, in total there are around 11.000. But to isolate the problem I am right now only creating the items of the first and second level, leaving the relationship out, those are 9043 objects.

我开始检查金额的内存使用,因为应用程序崩溃在进程的结束(与完整的数据集)。第一次内存检查是在内存中加载json之后,所以测量真的只考虑到对象的创建和插入到Core Data。我用来检查所使用的内存是这段代码(

I started checking the amount of memory used, because the app was crashing at the end of the process (with the full data set). The first memory check is after loading in memory the json, so that the measurement really takes only in consideration the creation, and insert of the objects into Core Data. What I use to check the memory used is this code (source)


-(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)&info,
                                   &size);
    if( 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只需要创建/更新/删除数据。

The BMC is independent to the MMC, so BMC is no child context of MMC. And they do not share any parent context. I don't need BMC to notify changes to MMC. So BMC only needs to create/update/delete the data.

Plaform:


  • iPad 2和3

  • iOS,我已经测试将部署目标设置为5.1和6.1。没有区别

  • XCode 4.6.2

  • ARC

  • iPad 2 and 3
  • iOS, I have tested to set the deployment target to 5.1 and 6.1. There is no difference
  • XCode 4.6.2
  • ARC

问题:
导入数据,使用的内存不会停止增加,iOS似乎不能耗尽内存,即使在过程结束后。

Problem: Importing the data, the used memory doesn't stop to increase and iOS doesn't seem to be able to drain the memory even after the end of the process. Which, in case the data sample increases, leads to Memory Warnings and after the closing of the app.

研究:


  1. Apple文档

  1. Apple documentation

  • Efficiently importing Data
  • Reducing Memory Overhead

将数据导入到Core Data时记住的要点(

Good recap of the points to have in mind when importing data to Core Data (Stackoverflow)

测试完成并分析内存释放。他似乎有和我一样的问题,他发送了一个苹果Bug报告没有从苹果的反应。 (来源

Tests done and analysis of the memory release. He seems to have the same problem as I, and he sent an Apple Bug report with no response yet from Apple. (Source)

导入和显示大型数据集(

Importing and displaying large data sets (Source)

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

Indicates the best way to import large amount of data. Although he mentions:


我可以在稳定的3MB内存中导入数百万条记录,而不用
调用-reset。

"I can import millions of records in a stable 3MB of memory without calling -reset."

这让我觉得这可能是有可能的吗? (

This makes me think this might be somehow possible? (Source)

测试


  • 关闭了关系的创建,因为文档说他们是昂贵的。

  • 未执行提取操作

代码:
$ b

Code:


- (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 
}

测量:

它从16.97 MB到30 MB,到28 MB。每5秒重复一次get_memory调用,内存保持为28 MB。

It goes from 16.97 MB to 30 MB, after the sync it goes down to 28 MB. Repeating the get_memory call each 5 seconds maintains the memory at 28 MB.

没有运气的其他测试:


  • 重新创建持久存储,如研究中所示2)没有效果

  • 测试让线程等待一会看看内存是否恢复,例4)

  • 在整个过程之后将上下文设置为nil

  • 在任何时候执行整个过程而不保存上下文(丢失信息)。实际上,作为结果维护较少的内存,留下它在20 MB。但它仍然不减少,我需要信息存储:)

  • recreating the persistent store as indicated in research 2) has no effect
  • tested to let the thread wait a bit to see if memory restores, example 4)
  • setting context to nil after the whole process
  • Doing the whole process without saving context at any point (loosing therefor the info). That actually gave as result maintaing less amount of memory, leaving it at 20 MB. But it still doesn't decrease and... I need the info stored :)

也许我错过了一些东西,但我真的测试了很多,遵循指南后,我预计会看到内存再次下降。我已经运行Allocations仪器来检查堆的增长,这似乎也很好。也没有内存泄漏。

Maybe I am missing something but I have really tested a lot, and after following the guidelines I would expect to see the memory decreasing again. I have run Allocations instruments to check the heap growth, and this seems to be fine too. Also no memory Leaks.

我缺少想法来测试/调整...我真的很感激,如果有人可以帮助我的想法,我可以测试,或者可能指向我做错了。或者它就是这样,它是如何工作...我怀疑...

I am running out of ideas to test/adjust... I would really appreciate if anyone could help me with ideas of what else I could test, or maybe pointing to what I am doing wrong. Or it is just like that, how it is supposed to work... which I doubt...

感谢任何帮助。

EDIT

我已使用乐器配置活动监视器模板的内存使用情况,实际内存使用与在控制台中打印的 get_free_memory 相同,内存仍然不会被释放。

I have used instruments to profile the memory usage with the Activity Monitor template and the result shown in "Real Memory Usage" is the same as the one that gets printed in the console with the get_free_memory and the memory still never seems to get released.

推荐答案

确定这是相当尴尬...僵尸启用了方案,在参数上,他们关闭,但在诊断启用僵尸对象 ..

Ok this is quite embarrassing... Zombies were enabled on the Scheme, on the Arguments they were turned off but on Diagnostics "Enable Zombie Objects" was checked...

关闭此选项可保持内存稳定。

Turning this off maintains the memory stable.

感谢您阅读的问题,并尝试解决它!

Thanks for the ones that read trough the question and tried to solve it!

这篇关于核心数据导入 - 不释放内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆