0
votes

I have an OS X Cocoa cpplication (10.8-10.9) that opens very large NSDocument (Core Data backed) files that are about 2 GBs or bigger. This takes about 20-40 seconds with the initial load of the document, but then is pretty snappy. The 20-40 seconds doesn't exactly jive with a good UI experience, so I'd like to fix that.

I would like to either A) make the document opening faster, or B) show a "loading" screen.

I'm wondering what (if anything) folks have done to A) make opening a core data document faster (even if its doing stuff in the background) or B) display a splash screen / progress bar during the opening process.

WRT to B) (not a 2-part question, really, just wanted to demonstrate I have do research) showing a splash screen by creating methods in the NSDocument class works if calling during: windowControllerWillLoadNib and windowControllerDidLoadNib methods, but only after the first document has been opened (I'm sure there is a workaround). Either way, there is no "progress" that I can see that I could establish a hook into, anyway.

3
What does Instruments tell you? Where is it slow? That is step one in best practices.Marcus S. Zarra
Running instruments confirms my suspicion that this was a series of very long Core Data calls. _populateRowValuesOnBackgroundThread (CoreData) and [NSKeyedUnarchiver unarchiveObjectWithData:] take up most of the opening call time.Nathan Dunn
Posting the instruments trace will help to identify a potential solution. Just saying "Core Data" does not allow anyone to help you to solve the issue. What is in your Model? Is there binary data? The details are important.Marcus S. Zarra
My Core Data database is standard sqlite. There are 5 model objects. Of those objects, the largest has multiple NSData (genomic sequence data). This is gzipped compressed JSON that is rendered to HTML. Here is the trace file (can't post all text in comments): dl.dropboxusercontent.com/u/101534245/Instrument-Dump.trace.zipNathan Dunn
Here is the core data trace below. Long-story short, 30-40 seconds of fetching prior to the application loading. Most likely solution would be to over-ride makeDocumentWithContentsOfURL:ofType:error is NSDcoumentController and wire into the splash screen. dl.dropboxusercontent.com/u/101534245/…Nathan Dunn

3 Answers

0
votes

In addition to the specific hints Duncan gave you it's always useful to check out the latest (and free) WWDC videos on ADC to get an idea on the patterns provided by OS X and Cocoa in particular to boost an apps performance. Some starting points:

WWDC '12
- Asynchronous Design Patterns with Blocks, GCD, and XPC

WWDC '13
- Designing Code for Performance

0
votes

Try opening the store on a background thread and once it's open activate the UI - that seems to work OK.

I create a background thread to call the [psc addPersistentStoreWithType:configuration:URL:options:error:] and once that's complete I hand control back to the main thread where the managedObjectContext gets created and the UI enabled.

You face this issue if Core Data has to do a big upgrade to a new model version as well. Some of my files take around a minute and if they are in iCloud it can be even longer. And if the upgrade happens on an iOS device then it can take a few minutes so this seems to be important for iOS apps as well.

BTW I have posted sample apps here http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/

0
votes

What does -getLociWithChromsomes: do? What happens when you drill into that method in Instruments to see what is taking all the time?

Same question with -GetAllLoci: and -getMaxLocusSnps?

It appears from the small amount of data that I can see is that you are doing a ton of fetching on launch. That is a bad design no matter what platform you are on. You should avoid doing a lot of fetching during the launch of the document and delay it until after the initial document/application launch has completed.

You could use a multi-threaded design here and it probably would help but it is really masking the problem.

The core of the issue appears to be that you are trying to do too much on launch. I am not certain that the entire delay is in core data or what you are doing with the data once it is retrieved as I do not have code level access through the trace you provided. It would be interesting to see screenshots of those methods above in Instruments with the time percentages highlighted.

Update

Again, you are loading too much during launch and blocking the UI. You have three answers all saying the same basic thing. This is not a Core Data problem. This is a performance problem because you are loading too much on launch or you are doing too heavy of a calculation on launch.