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: mmalcolm crawford <email@hidden>
- Date: Tue, 20 Dec 2005 10:55:04 -0800
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:
This email sent to email@hidden