Proud Member
Proud Member

Reputation: 40496

Why should I prefer to create an NSManagedObjectContext for every new thread or NSOperation instead of calling Core Data on the Main thread?

Some developers already told me that I can create a new NSManagedObjectContext instance for every new thread, to make Core Data thread-safe. Then I would just have to take care of the merging afterwards.

For me, this sounds like A LOT of extra code and overhead.

Is there a reason why this solution would be bad? Here it comes:

Instead of creating a new MOC for every new thread or for every NSOperation, I would perform MOC-changes on the Main Thread, just like we know from UIKit. I would just call -performSelectorOnMainThread:...waitUntilDone:YES and get rid of all Core Data concurrency issues.

Pros: - Don't have to create a new MOC for every Thread / NSOperation. - Don't have to merge MOCs together. - For sure no concurrency issue since Core Data stays on the Main thread where it is safe.

Cons: - Calls like -performSelectorOnMainThread:...waitUntilDone:YES look ugly, hard to read. - Thread / NSOperation gets blocked. But in reality, the system can't do multiple things at once anyways. In my case, the Core Data part is not the performance bottleneck. It's the heavy calculations around it that go in a background thread or NSOperation.

What do you think? Is this worth exploring further? Why would you still prefer to create a MOC for every new Thread / NSOperation and then deal with merging? What's the advantage of this compared to doing it on the Main thread?

Upvotes: 4

Views: 1117

Answers (2)

octy
octy

Reputation: 6545

"Disk access is expensive" - we've been told...

If you fetch or save lots of data, there is an advantage of using a separate MOC on a NSThread/NSOperation. Coupled with a view transition, this can well improve the perception of "speed" in your application, since the main thread is left to perform only the UI transition stuff.

I think you could find your answer by measuring how much time you actually spend accessing your store vs your UI responsiveness (IIRC: try the CoreData and CoreAnimation Instruments), and compare both scenarios: using a different MOC per thread vs. calling -performSelectorOnMainThread:...waitUntilDone:YES

BTW, if you save on a background thread, you also need to consider what happens when your app is terminated while a save operation is in progress. Background threads get killed right away, whereas the watchdog waits 5 seconds for the main thread to finish up.

Upvotes: 1

TechZen
TechZen

Reputation: 64428

The major reason to perform intensive operations on a background thread/operation is that the UI runs on the front/main-thread. If you have an intensive Core Data operation running on the main thread, the UI will be unresponsive and possibly making the user think the app has hung up or crashed. Since most apps everywhere show at least some motion while working intensively, user's have been trained to expect that an unresponsive or static UI indicates a crash or hang.

Mobile users are also way more sensitive to wait times. If your setting at your desk sipping a cup of coffee, a 45 second pause doesn't seem to long. If you're walking through an airport it does.

Removing intensive operations off the main thread allows the UI to continue to function. In some cases, this means the user can keep working, in others it means you can dynamically update the UI to communicates that the app is working on an intensive operation and that is why the user has to wait.

That makes a major impact on how users perceive the quality and usability of your app.

Having said that, I wouldn't bother with using background thread/operations until you've tested the app and found that Core Data can't handle processing on the main thread. In the vast, majority of cases, it can. Slow downloads from servers are probably the major driver of the need for background operations. If you don't have those, chances are very good your app won't need any serious backgrounding.

Upvotes: 5

Related Questions