gpt4 book ai didi

ios - 核心数据executeFetchRequest消耗大量内存

转载 作者:可可西里 更新时间:2023-11-01 05:04:33 26 4
gpt4 key购买 nike

我正在向核心数据数据库中插入大约 100 000 条记录。数据库包含 3 个实体。球员、俱乐部、球员俱乐部实体在关系中:球员<-->>球员俱乐部<<-->俱乐部在 PlayerClub 中插入时,我注意到在插入大约 50 000 条记录后会消耗大量内存并降低速度。记录永远不会更新,因为 PlayerClub 只有唯一值。出于测试原因,我清空了 Player 和 Club 表并再次运行该程序。没有速度下降,但内存消耗再次巨大。这是代码:

    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 方法基本相同,所以我不想发布它。这段代码被调用了大约 100 000 次。之前的内存消耗约为 150 MB。完成其 650 MB 后。所以它消耗了 500 MB,没有保存上下文,也没有从数据库中获取任何东西,因为表是空的。如果我评论

arTmp = [context executeFetchRequest:request error:&error];

DohvatiIgracZaIgracId 和 DohvatiKlubZaKlubId 方法中的行内存消耗降至 200 MB。因此,对于一行什么都不做的代码,差异是 400MB。这不可能。任何人都有一些想法。一段时间后,我的应用消耗了超过 2.5 GB。

这些测量是在模拟器上完成的,因为我需要构建一个稍后预加载的数据库,所以速度很重要:)...提前致谢

最佳答案

without saving the context

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

您应该考虑的其他一些事项:

  • 不要一次获取一个对象。获取相对昂贵。如果您运行 100k 个实例并一次获取一个,您的代码将花费几乎所有时间来执行获取。分批获取 50-100(您可以调整数量以获得速度与内存使用的最佳平衡)。处理一批,然后在批结束时保存更改。

  • 当您完成获取的对象时,告诉托管对象上下文您已完成。通过将 NO 作为第二个参数调用 refreshObject:mergeChanges: 来完成此操作。这告诉上下文它可以释放它用于对象的任何内部内存。这会丢失对象上所有未保存的更改,但如果您没有进行任何更改,则不会丢失任何内容。

  • 考虑完全摆脱 PlayerClub 实体。 Core Data 支持多对多关系。这种实体几乎从来没有用过。您使用的是 Core Data,而不是 SQL,所以不要像使用 Core Data 一样设计您的实体类型。

关于ios - 核心数据executeFetchRequest消耗大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19952716/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com