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: Thu, 20 Aug 2009 13:28:35 -0700
On Aug 20, 2009, at 2:34 AM, Ruotger Skupin wrote:
Am 19.08.2009 um 22:00 schrieb Ben Trumbull:
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 ?
I'm not using a predicate for the first fetch. (Ok, I have learned
now, I should do so.)
Okay, but what was the predicate you were passing to
filteredArrayUsingPredicate: ?
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).
Yes I do some on-the-fly filtering which depends on other objects.
(Ok, lesson learned: Bad idea)
Dynamic filtering isn't necessarily bad. The goal is always to
perform the least amount of I/O and consume the least amount of
memory. This produces the best performance.
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.
So, would it be better to perform the on-the-fly filtering
calculation every time the object changes and put flags in the root
object? Then fetch with a predicate testing these flags? Probably.
(model change! yay!)
Uhm, I think we're getting way ahead of ourselves. That's probably
serious overkill for the problem you're currently facing.
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.
That's what I'm doing now because the most common use case is: I
need almost everything. So the approximation is: I fetch everything
and filter out some objects.
Well, we can provide better suggestions with the actual filtering
predicate you're using. But the primary point here is that you're NOT
fetching everything. You're only fetching the objects on one side of
a relationship, but filtering based on information across a
relationship.
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.
The subsets depend on the data of the objects. (Smart Folders)
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.
Isn't all text Unicode? I don't understand. This shouldn't be a
special case. But I will have a look at the sample.
You can HAVE as much Unicode text as you want. That's just bytes.
But performing regex or CONTAINS searches on Unicode text is very
expensive.
In my case I'd guess that at least half of the objects contain
unicode strings (international names and addresses). What I want to
say: write anything in German or French and you end up with Unicode.
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.
As stated before I need almost all data anyway. Is there a way to
bulk-load the whole database into mem in one go? That's not what sql
is about, is it?
setRelationshipKeyPathsForPrefetching
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.
Ok, will try to do that.
Another question: I'm using Garbage Collection. Should I look out
for something special there? Keep managed objects on purpose?
Letting them go as soon as possible?
One thing at a time. Add the appropriate prefetching to your fetch
request and then reprofile the app.
- 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