核心数据在后台线程上缓慢处理更新

Posted

技术标签:

【中文标题】核心数据在后台线程上缓慢处理更新【英文标题】:Core data slow processing updates on a background thread 【发布时间】:2016-03-03 00:25:22 【问题描述】:

在后台线程上处理更新时,我的应用程序速度存在重大问题。 Instruments 显示,几乎所有这些时间都花在了 performBlockAndWait 内,我在那里提取需要更新的对象。

根据离线时间的长短,我的更新可能会成百上千次,而我目前使用的方法是单独处理它们;即获取请求以提取对象,更新,然后保存。

听起来很慢,确实如此。我遇到的问题是我不想一次将所有内容加载到内存中,因此需要在进行时单独获取它们,并且我会在进行时保存以确保如果单个更新出现问题,它将不会别搞砸了。

有更好的方法吗?

【问题讨论】:

【参考方案1】:

在插入大量对象时,我遇到了类似的缓慢性能。就我而言,我愿意将完整的更改集保留在内存中并执行一次保存,因此大量的获取请求占据了我的处理时间。

通过维护内存缓存将我的资源主键映射到NSManagedObjectIDs,我获得了显着的性能提升。这让我可以使用 existingObjectWithId:error: 而不是对单个对象的获取请求。

我怀疑我可能会做得更好,方法是收集给定实体描述的所有资源的主键,一次为所有资源发出单个提取请求(根据需要批量处理这些结果),然后处理对每个资源的更改资源。

【讨论】:

【参考方案2】:

假设您只针对 ios 8+,您可能会从使用 NSBatchUpdateRequest 中受益。

These guys have a great example of it 但 TLDR 基本上是:

示例:假设我们要更新 MyObject 的所有未读实例以标记为已读:

NSBatchUpdateRequest *req = [[NSBatchUpdateRequest alloc] initWithEntityName:@"MyObject"];
req.predicate = [NSPredicate predicateWithFormat:@"read == %@", @(NO)];
req.propertiesToUpdate = @
    @"read" : @(YES)
;
req.resultType = NSUpdatedObjectsCountResultType;
NSBatchUpdateResult *res = (NSBatchUpdateResult *)[context executeRequest:req error:nil];
NSLog(@"%@ objects updated", res.result);

注意上面的例子取自前面的博客,sn-p不是我写的。

【讨论】:

这些更新无论如何都没有关系,所以我不知道如何批量处理它们。 啊,我明白了。没有从原始问题中收集到它们是不相关的更新。那么你可能会不走运,除非你可以将它们分批。例如,假设您有 A、B 和 C 类型的更新,您可以将它们单独排队,然后定期对所有 A 进行批量更新,对所有 B 进行批量更新等。

以上是关于核心数据在后台线程上缓慢处理更新的主要内容,如果未能解决你的问题,请参考以下文章

核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为啥?

在后台线程中更新托管对象上下文

从后台线程保存数据时核心数据崩溃

作为 UIBackgroundTask 运行时,后台线程上的核心数据迁移失败

删除核心数据对象并保存在后台线程中

线程化核心数据和 UINavigationController