我很好奇创建Fetch Request模板与以编程方式创建NSFetchRequest相比是否会提高性能,所以我写了一些测试来衡量这一点。Here's the source on github。
模拟器和iPhone (测量执行大量获取的时间间隔)的差异顺序相同:
just creating an NSFetchRequest: 4.399674
creating a Fetch Request Template: 0.501369
NSFetchRequest with field indexed: 0.407068
Fetch Request Template and field indexed: 0.281876
事实证明,创建一个Fetch请求模板大约有7~9倍的性能提升。我认为它可能在底层创建了适当的索引,但当我创建了一个与索引字段匹配的Fetch请求模板时,甚至还有更多的性能优势。
好吧,很高兴知道是这样的,但我非常想知道在Fetch请求模板下发生了什么,这说明了性能的提高?
发布于 2012-07-02 20:38:51
更新
在使用Instruments进行了一些分析之后,事实证明[NSPredicate predicateWithFormat:]
不是罪魁祸首!
造成性能差异的实际原因是排序描述符。
非模板测试使用NSFetchedResultsController
,它需要一个排序描述符,而基于模板的测试没有指定排序描述符。
如果将排序描述符添加到所有测试中,性能将趋于平衡(索引用例除外)。
原始(错误)答案
性能损失是因为您的“只创建一个NSFetchRequest”测试为循环的每次迭代调用[NSPredicate predicateWithFormat:]
-这非常慢!
想想看- [NSPredicate predicateWithFormat:]
必须解析字符串,并基本上将其编译成核心数据使用的内部表示形式。
通常的解决方案是只调用[NSPredicate predicateWithFormat:]
一次,然后使用[NSPredicate predicateWithSubstitutionVariables:]
指定将与谓词进行比较的值-这在Core Data Documentation - Efficiently Importing Data中有介绍
要从格式化字符串创建谓词,框架必须解析字符串并创建谓词和表达式对象的实例。如果您多次使用相同形式的谓词,但每次使用时都更改其中一个常量值表达式的值,则创建一次谓词然后使用变量替换会更有效(请参阅“创建谓词”)。
发布于 2012-07-02 14:50:01
存储的fetch请求可以包括用于变量替换的占位符,因此可以作为以后完成的模板。因此,Fetch请求模板允许您使用在运行时替换的变量预定义查询。
另外,请参阅NSManagedObjectModel Class Reference的存储获取请求部分。
似乎最大的优势可能来自这样一个事实,即查询不必在运行时构建--它是预先构建的,然后在适当的时候将变量替换到查询中。
https://stackoverflow.com/questions/11175474
复制相似问题