Re: Threads and Core Data, bindings results in view corruption
Re: Threads and Core Data, bindings results in view corruption
- Subject: Re: Threads and Core Data, bindings results in view corruption
- From: Ben Lachman <email@hidden>
- Date: Sun, 30 Mar 2008 22:50:30 -0400
Ben:
I was actually just uncovering some of this stuff myself. In my
particular case I am mostly doing inserts so while the KVC stuff is
interesting and very well may be useful at some point, it doesn't
apply to my current situation.
My problem is that I receive data from a connection and process it in
my one worker thread sequentially. After each batch I save the
worker thread's MOC and send a bunch of OIDs back to the main
thread. I think this is the approved way of doing things. The
issues lie in the fact that, depending on several things, batches
often end up being rather small which makes saves rather frequent.
Last night (morning) after posting I spent some time in shark and
save: was burning up >50% of the time in my worker thread. With a
little work to coalesce batches and sleep instead of immediately
exiting (in hope that a new batch might come in) I've gotten that
number down to around 40%. However this is still quite substantial
and I'd like to get it down into the 25% range. The trick is just
trying to figure out ways to save less frequently, without letting
the UI go too stale. One of the biggest performance improvements so
far has been to coalesce pending batches into a single larger
batch... this makes the sorting behavior of my UI a bit more "chunky"
than I'd like, but I think is acceptable as it cuts a second or so
off the length to completion of normal searches.
I'm guessing the bugs really should be filed on the documentation
since one page on performance of a highly complex API like CD is
nowhere near enough. My guess is that documentation doesn't get as
many bugs as it should since it is, at the point of the developer
filing the bug, no longer a road block and therefore is kind of seen
(wrongly) as a waste of time since it is just for the greater good of
the dev community not getting your project done.
Thanks for the feedback it was quite helpful. Any thoughts or tricks
to reduce the frequency of saving in worker threads would be welcome,
but I think I'm now on the right path.
->Ben
--
Ben Lachman
Acacia Tree Software
http://acaciatreesoftware.com
email@hidden
740.590.0009
On Mar 30, 2008, at 9:50 PM, Ben Trumbull wrote:
David, Jeff, Ben
There are a few issues here.
First, enough pieces of AppKit and Cocoa Bindings are not thread
safe that, even without Core Data, you just can't do this in this
particular fashion.
If you want multi-threaded work with the view and controller
classes in Cocoa, you'll need to perform your background
operations, and communicate back to the main thread (view &
controllers) via the run loop. -performSelectorOnMainThread and
its friends in NSThread.h are your best bet.
Using a run loop on a background thread and communicating from the
main thread to it with the new 10.5 -performSelector... methods is
often conceptually simpler (easier to debug) than many other
threading patterns.
Sharing a MOC with Cocoa Bindings and a background thread will end
in tears. Cocoa Bindings doesn't lock its bound MOC, so you're
basically SOL.
Even if it did work, though, it'd be a bad idea. Sharing a MOC
means a background thread would still at times block the main
thread and SPOB your app.
These 3 points (can't work, doesn't work, shouldn't work) are why
the Core Data Programming Guide says don't do this.
This isn't to say what what you intend to accomplish is wrong or
undesirable. Quite the contrary. Just that this 'how' is going in
the wrong direction.
The Core data programming guide says its best to maintain a separate
managedObjectContext per thread. But this appears to require the
data to be
written to persistent store to make it work (file). That not
reasonable in
my case where I'm adding many objects to an object tree. It takes a
significant amount to time to write it out, negating the benefit
of trying
to make the UI seem responsive.
The list archives also have these, which you should read:
<http://lists.apple.com/archives/cocoa-dev/2007/May/msg00222.html>
<http://lists.apple.com/archives/cocoa-dev/2008/Jan/msg01889.html>
It's possible to shuttle pending changes between threads by hand
using KVC.
On Tiger, saves are especially expensive as the default behavior
was to use a more correct/aggressive version of fsync, specifically
fcntl(...,F_FULLFSYNC). This is 100-1000x slower than fsync, which
technically is incorrect on nearly all consumer grade hard drives
at a hardware level.
On Leopard, we made significant performance optimizations, so the
user experience can vary greatly between the two OS's.
If you're inserting a large number of new objects, you really
should just batch the operation together, save, and present the
user with new objects in the tree view in batches.
On Leopard, in the scenarios under which you can save, you can also
use -mergeChangesFromContextDidSaveNotification:
While AppKit & Bindings makes it impossible to share a MOC with a
background thread, theoretically all your background threads can
share a MOC if you lock and unlock them. Or you could just have 1
background thread processing asynchronous operations. That'd be a
lot easier to debug.
You should also use the Debug libraries and Core Data multi-
threaded assertions:
<http://lists.apple.com/archives/cocoa-dev/2008/Mar/msg01098.html>
Life's a lot easier when your app halts in gdb as soon as you make
a mistake. 'thread apply all bt' is your friend.
Finally, in 4 years no one has filed a bug about this.
If one developer has a problem, it's unfortunate. If three
developers have a problem, it's an issue. If two hundred
developers have a problem, it's a crisis.
Kinda hard to tell the difference if developers can't be bothered
to speak up in the only way that really matters: bugerport.apple.com
Feature requests, performance problems, and enhancement suggestions
are all "bugs"
_______________________________________________
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