re: Core Data dog-slow when using first time after boot
re: Core Data dog-slow when using first time after boot
- Subject: re: Core Data dog-slow when using first time after boot
- From: Ben Trumbull <email@hidden>
- Date: Wed, 19 Aug 2009 13:00:58 -0700
when fetching about 5000 objects from an sql store, Core Data is very
slow the very first time after a boot. When running the app the first
time it takes 50 to 90 seconds and when starting it the second time it
is well below one second.
Properly done, you could fetch 5000 objects on an original iPhone in a
couple of seconds (or even less, depending on the NSFetchRequest
options). On a Mac Pro, your performance is off by two orders of
magnitude. If you wanted a result set, but didn't need all of it at
once, you could use setBatchSize and handle about 3 million rows per
second on a Mac Pro.
Have you profiled your application ? Have you run Instruments on your
app with the Core Data template ? It'll provide Core Data specific
information about faulting, fetching and saving which pairs well with
the more general CPU sampler.
According to shark basically nothing plus some time spend in faults.
Shark is useless when perf-debugging Core Data.
Shark is very good at telling you where you are doing something
expensive. Shark has just given you really valuable information (too
many faults being tripped) and where in your code you are doing this
expensive thing. Instead of describing that as useless, perhaps you
should consider reducing the number of faults being tripped ...
I debugged it with some Snow Leopard magic and found out, that firing
faults is very slow the first time after boot. When I use -[NSArray
filteredArrayUsingPredicate:] the fault firing is killing me.
What's the predicate you are using ?
You're almost certainly filtering in memory after fetching only a
subset of the data needed to perform your in memory filtering
(specifically, only the source entity and not its relationships).
Since you didn't fetch the related objects, Core Data goes and
retrieves them on demand. However, mind reading is technically
challenging, and Plan B, retrieving the related objects one at a time,
is a rather inefficient I/O pattern.
It would be vastly faster to filter the data in the database using a
predicate on the fetch request. If that's not possible, then you
should use a fetch request predicate that approximates what you need,
and filter those results more precisely in memory. Like a bounding
rect in views. If you have already fetched the objects, but want to
identity different subsets, you can use objectID fetch results to
simply identify the matching objects without pulling back all the row
data.
Complex locale aware Unicode text queries can be slow. If you find
yourself spending time with such a query, you should consider some of
the techniques shown in the DerivedProperty example available on ADC.
What is going on here?
Typically, apps that launch slowly once, and then run quickly
afterwards are doing far too much I/O. On successive launches, the
kernel has cached most of the data, so instead of doing to-disk I//O
the app is doing to-kernel-memory I/O.
The most common problem in Core Data apps is when people allow
faulting to lazily fetch data one row at a time, even when the app
needs all the data immediately. They should prefetch the related
objects with the original fetch request by setting the prefetching
keypaths.
Have you read through the Core Data Programming Guide's chapter on
Performance ?
<https://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdPerformance.html#//apple_ref/doc/uid/TP40003468
>
So I recoded it to fetch everything upfront with [fetchRequest
setReturnsObjectsAsFaults:NO];
This isn't solving the problem you expect. You'll want to use
prefetching and should read the programming guide.
Pre-fetching: not tried
But if I understand the document right it's just a special case of
Batch Faulting and I don't see any faults fired since I use Batch
Faulting anyway
No, prefetching is not a special case of batch faulting. Batch
faulting is about taking N objects (or objectIDs) and telling Core
Data "I want all of these, now". Prefetching is about telling Core
Data "I want the objects that match this fetch request, plus all of
their related friends X and Y.Z"
- Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden