在提取请求模板下面发生了什么改善性能?

Jin*_*Kim 19 iphone cocoa cocoa-touch core-data ios

我很好奇是否通过创建获取请求模板而不是以编程方式创建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
Run Code Online (Sandbox Code Playgroud)

事实证明,创建获取请求模板的性能提升约为7~9倍.我想也许它正在创建下面的正确索引但是当我创建一个匹配索引字段的获取请求模板时,甚至还有一个性能优势.

好的,很高兴知道这种情况,但我非常想知道在获取性能增益的获取请求模板下发生了什么?

Nic*_*ell 8

更新

经过仪器的一些分析,事实证明[NSPredicate predicateWithFormat:]这不是罪魁祸首!

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

非模板测试使用an NSFetchedResultsController,这需要排序描述符,而基于模板的测试不指定排序描述符.

如果为所有测试添加排序描述符,性能会均匀(除了索引的情况外).


原(错)答案

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

想一想 - [NSPredicate predicateWithFormat:]必须解析字符串并基本上将其编译为Core Data使用的内部表示.

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

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