首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >核心数据executeFetchRequest消耗大量内存。

核心数据executeFetchRequest消耗大量内存。
EN

Stack Overflow用户
提问于 2013-11-13 11:34:32
回答 1查看 1.7K关注 0票数 4

我在核心数据数据库中插入cca 10万条记录。数据库包含3个实体。Player,Club,PlayerClub实体之间存在关系:Player<-> PlayerClub <-->Club在插入PlayerClub时注意到在插入大约5万条记录后,内存消耗和速度下降。记录从不更新,因为PlayerClub只有唯一的值。出于测试的原因,我已经清空了球员和俱乐部的桌子,并再次运行程序。没有速度下降,但内存消耗再次巨大。这是代码:

代码语言:javascript
复制
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
    [context setPersistentStoreCoordinator:ap.persistentStoreCoordinator];
    [context setUndoManager:nil];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"PlayerClub"
                                              inManagedObjectContext:context];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];

    NSEntityDescription *entityKlubovi = [NSEntityDescription entityForName:@"Club" inManagedObjectContext:context];
    NSFetchRequest *requestKlubovi = [[NSFetchRequest alloc] init];
    [requestKlubovi setEntity:entityKlubovi];
    [requestKlubovi setFetchLimit:1];

    NSEntityDescription *entityIgraci = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:context];
    NSFetchRequest *requestIgraci = [[NSFetchRequest alloc] init];
    [requestIgraci setFetchLimit:1];
    [requestIgraci setEntity:entityIgraci];

    for (int i=0; i<[parsedKlubIgraci count]; i++) {
        @autoreleasepool {
            KlubIgrac *klubIgrac = [[KlubIgrac alloc] initWithEntity:entity insertIntoManagedObjectContext:context];

            klubIgrac.iD = p.id;

            //... add some othe properties

            variables = [NSDictionary dictionaryWithObject:p.igracID forKey:@"ID"];
            localPredicate = [predicateIgraci predicateWithSubstitutionVariables:variables];
            [requestIgraci setPredicate:localPredicate];
            klubIgrac.igrac = [self DohvatiIgracZaIgracId:p.igracID cntx:context request:requestIgraci predicate:localPredicate];

            variables = [NSDictionary dictionaryWithObject:p.klubID forKey:@"ID"];
            localPredicate = [predicateKlubovi predicateWithSubstitutionVariables:variables];
            [requestKlubovi setPredicate:localPredicate];
            klubIgrac.klub = [self DohvatiKlubZaKlubId:p.klubID cntx:context request:requestKlubovi predicate:localPredicate];
        }

    }
+(Club *)DohvatiKlubZaKlubId:(int)klubid cntx:(NSManagedObjectContext *)context    

    request:(NSFetchRequest *)request predicate:(NSPredicate *)predicate
{
    @autoreleasepool {
        NSError *error;
        NSArray *arTmp;
        arTmp = [context executeFetchRequest:request error:&error];
        Club *klub;
        if(arTmp != nil && [arTmp count]){
            return [arTmp objectAtIndex:0];
        }
    }

}

DohvatiIgracZaIgracId方法基本上是与DohvatiKlubZaKlubId相同的方法,所以我没有发布它。这个代码被调用了大约10万次。以前的内存消耗约为150 MB。在它完成650 MB之后。因此它消耗500 MB,不保存上下文,也不从数据库中获取任何内容,因为表是空的。如果我评论

代码语言:javascript
复制
arTmp = [context executeFetchRequest:request error:&error];

在DohvatiIgracZaIgracId和DohvatiKlubZaKlubId方法中,内存消耗降到200 MB。因此,对于一行代码来说,差异是400 So,它什么也不做。这不可能。任何人都有自己的想法。过了一段时间,我的应用程序消耗超过2.5GB。

这些数据是在模拟器上完成的,因为我需要建立一个数据库,稍后我将预加载数据库,因此速度非常重要:)Thx预先

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-13 17:33:55

而不保存上下文

这是问题的一部分,经验丰富的核心数据开发人员说“哦,天哪”。这就是你最大的问题。定期保存更改--每50个条目,或每100个条目,但无论做什么,都不要等到完成。您强迫Core数据将所有这些对象作为未保存的更改保存在内存中。这是你有记忆问题的最大原因。

还有一些你应该考虑的事情:

  • 不要一次只取一件东西。胎儿相对来说很贵。如果您运行100 k实例并一次获取其中的每个实例,那么您的代码将花费几乎所有的时间执行获取。取50到100的批次(您可以调整数字以获得速度与内存使用的最佳平衡)。处理一个批处理,然后在批处理结束时保存更改。
  • 当您完成一个获取的对象时,告诉托管对象上下文您已经完成了。为此,使用refreshObject:mergeChanges:作为第二个参数调用NO。这告诉上下文它可以释放用于对象的任何内部内存。这将丢失对对象的任何未保存的更改,但是如果您没有进行任何更改,那么就没有什么可丢失的了。
  • 考虑完全摆脱PlayerClub实体。核心数据支持多到多的关系。这种实体几乎从来没有用过。您使用的是核心数据,而不是SQL,所以不要像设计实体类型那样设计实体类型。
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19952716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档