I was curious if there was a performance gain from creating a Fetch Request Template versus programmatically creating NSFetchRequest so I wrote some tests to measure this. Here’s the source on github.
Same order of difference in Simulator and on iPhone (measuring time interval to do a bunch of fetches):
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
It turns out there’s about 7~9 times performance gain in creating a Fetch Request Template. I thought maybe it’s creating the proper index underneath but when I created an Fetch Request Template that matches on an indexed field, there’s even a further performance benefit.
Ok, nice to know that this is the case, but I would very much like to know what the heck is happening underneath the Fetch Request Template that accounts for performance gains?
Update
After some profiling with Instruments, it turns out
[NSPredicate predicateWithFormat:]is not the culprit here!The actual cause of the performance difference is sort descriptors.
The non-template tests are using an
NSFetchedResultsController, which requires a sort descriptor, whereas the template-based ones do not specify a sort descriptor.If you add a sort descriptor to all the tests, the performance evens out (with the exception of the indexed case.)
Original (wrong) answer
The performance penalty is because your ‘just creating a NSFetchRequest’ test calls
[NSPredicate predicateWithFormat:]for each iteration of the loop – this is very slow!Think about it –
[NSPredicate predicateWithFormat:]has to parse the string and basically compile it into the internal representation used by Core Data.The usual solution is to only call
[NSPredicate predicateWithFormat:]once, and then use[NSPredicate predicateWithSubstitutionVariables:]to specify the values that will be compared by the predicate – this is covered in the Core Data Documentation – Efficiently Importing Data