19

我很好奇创建 Fetch 请求模板与以编程方式创建 NSFetchRequest 相比是否会带来性能提升,因此我编写了一些测试来衡量这一点。这是 github 上的源代码

Simulator 和 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 Request Template 大约有 7~9 倍的性能提升。我想也许它在下面创建了正确的索引,但是当我创建一个与索引字段匹配的获取请求模板时,甚至还有进一步的性能优势。

好的,很高兴知道是这种情况,但我非常想知道在 Fetch Request Template 下到底发生了什么导致性能提升?

4

2 回答 2

8

更新

在使用 Instruments 进行一些分析之后,事实证明[NSPredicate predicateWithFormat:]这不是罪魁祸首!

性能差异的实际原因是排序描述符

非模板测试使用NSFetchedResultsController,它需要一个排序描述符,而基于模板的测试不指定排序描述符。

如果您向所有测试添加排序描述符,则性能会变得均衡(索引案例除外。)


原始(错误)答案

性能损失是因为您[NSPredicate predicateWithFormat:]为循环的每次迭代调用“只是创建一个 NSFetchRequest”测试 - 这非常慢

想想看 -[NSPredicate predicateWithFormat:]必须解析字符串并将其编译成 Core Data 使用的内部表示。

通常的解决方案是只调用[NSPredicate predicateWithFormat:]一次,然后用于[NSPredicate predicateWithSubstitutionVariables:]指定将由谓词比较的值 - 这在核心数据文档中有所介绍 - 高效导入数据

要从格式化字符串创建谓词,框架必须解析字符串并创建谓词和表达式对象的实例。如果您多次使用相同形式的谓词,但每次使用时更改其中一个常量值表达式的值,则创建一次谓词然后使用变量替换会更有效(请参阅“创建谓词”)。

于 2012-07-02T12:38:51.367 回答
1

文档中:

存储的提取请求可以包含用于变量替换的占位符,因此可以用作稍后完成的模板。因此,获取请求模板允许您使用在运行时替换的变量来预定义查询。

此外,请参阅NSManagedObjectModel 类参考的存储获取请求部分。

似乎最大的优势可能来自查询不必在运行时构建的事实——它是预先构建的,然后在适当的时候将变量替换到查询中。

于 2012-07-02T06:50:01.193 回答