Re: [CORE DATA] BackgroundFetching app explanation, and more...
Re: [CORE DATA] BackgroundFetching app explanation, and more...
- Subject: Re: [CORE DATA] BackgroundFetching app explanation, and more...
- From: Aurélien Hugelé <email@hidden>
- Date: Wed, 21 Dec 2005 08:06:37 +0100
Thanks to have responded to my "rant", i'll take time to understand
every points you provided, because it seems the most detailed
explanation i could get. Some points are quite hard to understand,
and i need to read them several times !
From my own experience, there is more than 25% of difference between
firing a fault and not firing it (thanks to have corrected my
faulting vocabulary ;-) ). But i should have done something wrong and
i'll go back to my tests.
Aurelien
On 20 déc. 05, at 19:55, mmalcolm crawford wrote:
On Dec 19, 2005, at 10:38 AM, Aurélien Hugelé wrote:
As several people knows, fetching and unfaulting 50 000 objects
with core data is slow
Some notes about faulting and performance (with thanks to BT):
CoreData faults are analogous to virtual memory page faults. They
are simply scoped to objects instead of memory pages. Faults are
triggered, caused, experienced or "fired" when you access something
that you know about but don't yet have.
The performance of faulting (triggering a fault) depends on whether
or not you have data in the cache (held by the
NSPersistentStoreCoordinator). Cache hits are very fast. This is
the same speed as normal NSManagedObject initialization. Cache
misses are expensive. Just like virtual memory page faults. A
cache miss for a CoreData object fault causes CoreData to fetch
that data from the database. This is an I/O operation...
We avoid the term "unfaulting" because it's confusing. There's no
"unfaulting" a virtual memory page fault. Page faults are
triggered, caused, fired, or encountered; you can also release
memory back to the kernel in a variety of ways (vm_deallocate,
munmap, sbrk). CoreData describes this as "turning an object into
a fault". You turn a managed object into a fault using
refreshObject:mergeChanges: on the managed object context. Turning
a managed object into a fault releases unnecessary memory, nils out
properties, and releases any retains on related objects.
(See <http://developer.apple.com/documentation/Cocoa/Conceptual/
CoreData/Articles/cdFaultingUniquing.html>, <http://
developer.apple.com/documentation/Cocoa/Conceptual/CoreData/
Articles/cdFetching.html#//apple_ref/doc/uid/TP40002484-
DontLinkElementID_19>, and <http://developer.apple.com/
documentation/Cocoa/Conceptual/CoreData/Articles/cdMemory.html>.)
On a dual 2Ghz G5 (with adequate RAM and data access), you should
be able to fetch, fire the fault, perform -valueForKey:, release,
and deallocate approximately 24,000 objects per second. If you
want to simply fetch and deallocate (but not fire the fault or do
KVC) you should have a sustained throughput on that machine of
approximately 30,000 objects per second. The 25% difference is
split between KVC overhead and faulting overhead.
If you don't see comparable levels of performance (obviously,
larger objects will be proportionately slower to fetch), then
you're "doing something wrong".
"Something wrong" covers wide range of possibilities, including:
* Triggering faulting on objects you never fetched (i.e. cache
misses).
* Not being careful with the cost of one-to-many and many-to-many
relationships.
* Using large binary or text data as an attribute instead of across
a to-one relationship.
* Doing lots of text queries with complicated matching (such as
case insensitive LIKE '*foo*').
* Fetching more objects than you really need to work with at any
given moment.
* Not using entity inheritance well (you might not want it)
* Accidentally dirtying objects which ought be left unchanged.
Regarding the Background Fetching example. The key in this example
is to load the cache shared by the managed object contexts on
different threads (the cache is held by the persistent store
coordinator). This way, when the MOC on the main thread triggers
(fires) a fault, it is a cache hit (and hence very fast).
The comment in -fetchWordsForLetter: about faulting in the "words"
relationship refers to the issue with to-many relationships. To-
many relationships have two levels of faults. The first level of
faults are the contents (by identity/objectID) of the relationship
in an NSSet object. The second are the normal NSManagedObject
faults for each individual object associated by the relationship.
This code is explicitly triggering *just* the to-many relationship
fault. It doesn't need to trigger the faults for the individual
"word" objects because those have already been fetched at the
beginning of the method. If we don't touch those fetched words,
then we'll have loaded their data into the PSC cache via -
executeFetchRequest: without fully initializing them on the
background thread's MOC (where we don't need to use them).
The example then pushes a list of objectIDs to the main thread and
basically says "these objects are safe to use because I've pre-
loaded the cache with their data".
mmalc
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40gumitech.com
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden