Ant*_*Dev 4 iphone core-data ios
我在核心数据库中插入cca 100 000条记录.数据库包含3个实体.玩家,俱乐部,玩家俱乐部实体处于关系中:玩家< - >> PlayerClub << - >俱乐部插入PlayerClub后,我注意到在插入大约50,000条记录后,大量内存消耗和速度损失.记录永远不会更新,因为PlayerClub只有唯一值.出于测试原因,我已经清空了玩家和俱乐部表并再次运行程序.没有速度下降,但内存消耗再次巨大.这是代码:
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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
DohvatiIgracZaIgracId方法与DohvatiKlubZaKlubId基本相同,所以我发布它.此代码大约被调用10万次.以前的内存消耗大约是150 MB.完成650 MB之后.因此它消耗500 MB,而不保存上下文并且不从数据库中获取任何内容导致表为空.如果我评论
arTmp = [context executeFetchRequest:request error:&error];
Run Code Online (Sandbox Code Playgroud)
在DohvatiIgracZaIgracId和DohvatiKlubZaKlubId方法中,内存消耗降至200 MB.因此,对于一行无效的代码,差异为400MB.这不可能.任何人都有一些想法.一段时间后,我的应用程序消耗超过2.5 GB.
因为我需要建立一个我稍后会预加载的数据库,所以速度非常重要:)...提前了
Tom*_*ton 11
没有保存上下文
这是经验丰富的核心数据开发人员所说的"哦,圣洁的废话"的问题的一部分.那是你最大的问题.定期保存更改 - 每50个条目,或每100个条目,但无论你做什么,都不要等到你完成.您正在强制Core Data将所有这些对象保留在内存中作为未保存的更改.这是你遇到记忆问题的最大原因.
您应该考虑的其他一些事情:
不要一次取一个对象.取食相对昂贵.如果你运行100k个实例并一次一个地获取它们,你的代码几乎将花费所有时间来执行提取.批量获取50-100(您可以调整数量以获得速度与内存使用的最佳平衡).处理一批,然后在批处理结束时保存更改.
完成获取的对象后,告诉托管对象上下文您已完成.通过调用refreshObject:mergeChanges:with NO作为第二个参数来完成此操作.这告诉上下文它可以释放它用于对象的任何内部存储器.这会丢失对象上未保存的任何更改,但如果您没有进行任何更改,则不会丢失任何内容.
考虑PlayerClub完全摆脱实体.核心数据支持多对多关系.这种实体几乎从来没用过.您使用的是Core Data,而不是SQL,因此不要像使用那样设计实体类型.