核心数据:性能问题。 Instruments 的输出是神秘的

Posted

技术标签:

【中文标题】核心数据:性能问题。 Instruments 的输出是神秘的【英文标题】:Core Data: performance issue. Instruments's output is cryptic 【发布时间】:2014-04-24 15:37:26 【问题描述】:

我以基本方式使用 Core Data 和 RestKit(只是默认的 RestKit 设置)。

UI 有时会卡住很长时间(在 iPhone 5 上是 50 秒)。可以有很多对象,但没有什么疯狂的,而且对象很小(没有图像等)。

我怀疑这是由于一些上下文保存,但我不确定:我从来没有在我的应用程序中手动保存内容。

Instruments 的 Time Profiler 清楚地显示了卡住的原因,但我不明白输出或导致这种情况的原因。最重的堆栈跟踪如下所示:

14  57129.0  Main Thread  0x4ea79 :0
13 CoreData 56680.0  -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]
12 CoreData 56523.0  -[NSManagedObjectContext executeFetchRequest:error:]
11 CoreData 56462.0  -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]
10 CoreData 56442.0  -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]
 9 CoreData 56291.0  -[NSManagedObjectContext executeFetchRequest:error:]
 8 CoreData 50210.0  -[NSPersistentStoreCoordinator executeRequest:withContext:error:]
 7 CoreData 50193.0  -[NSMappedObjectStore executeFetchRequest:withContext:]
 6 CoreData 49978.0  -[NSDictionaryStoreMap handleFetchRequest:]
 5 Foundation 36516.0  -[NSPredicate evaluateWithObject:]
 4 Foundation 35865.0  -[NSComparisonPredicate evaluateWithObject:substitutionVariables:]
 3 Foundation 16845.0  -[NSFunctionExpression expressionValueWithObject:context:]
 2 CoreData 11823.0  -[NSDictionaryMapNode valueForKey:]
 1 CoreFoundation 1225.0  -[__NSCFString isEqualToString:]
 0 libobjc.A.dylib 36.0  -[NSObject class]

有人能指出正确的方向吗?

【问题讨论】:

看起来您正在主线程上执行一个长提取请求(在 CoreData 上保存 50 秒将是一个巨大的保存)。长操作(网络、数据库等)应该在后台线程上执行,然后更新到主线程上执行的 UI。 谢谢@RoboticCat。问题是我什至不知道是什么触发了这个获取(也不知道它实际上是什么)。它是通过私有 API _parentObjectsForFetchRequest 完成的。 某处(在您的代码中或在您包含的框架之一中)有大量的 CoreData 活动。这种情况发生在哪里,只有你自己知道;必须有一系列步骤导致此活动。我很惊讶您从未手动保存 CoreData(这是 UIManagedDocument 吗?),但无论如何您都必须弄清楚发生这种情况的位置。试一试Call Tree(如Hide System Libraries)中的复选框,这样您就可以尝试追踪调用CoreData 命令的内容。 另外,还有一个Core Data 分析选项;我不确定它是否会有所帮助,但其中可能有一些东西。 分析显示什么? RestKit 通常不会在主线程上运行任何 fetch... 【参考方案1】:

您是否尝试在核心数据设置期间将托管对象缓存设置为RKInMemoryManagedObjectCache?在 github 上看到此问题后,我尝试了此操作:https://github.com/RestKit/RestKit/issues/1232,它显着加快了我的 restkit/core 数据基准测试。下面是代码的样子:

objectManager.managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext: managedObjectStore.persistentStoreManagedObjectContext];

来自http://restkit.org/api/0.20.0/Classes/RKInMemoryManagedObjectCache.html 的 RestKit 文档:“(RKInMemoryManagedObjectCache) 提供快速的托管对象缓存,其中对象实例保留在内存中以避免命中核心数据持久存储。与基于获取请求的策略相比,性能大大提高内存消耗的代价。”

【讨论】:

以上是关于核心数据:性能问题。 Instruments 的输出是神秘的的主要内容,如果未能解决你的问题,请参考以下文章

iOS性能优化:Instruments使用实战

iOS性能优化:Instruments使用实战

iOS - 性能优化:Instruments使用简介

Instruments使用技巧

iOS性能优化:Instruments使用实战

IOS性能调优系列:使用Instruments动态分析内存泄漏