0

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.

bneely
  • 9,083
  • 4
  • 38
  • 46
Nathan Dunn
  • 447
  • 5
  • 16
  • 1
    What does Instruments tell you? Where is it slow? That is step one in best practices. – Marcus S. Zarra Feb 21 '14 at 21:54
  • 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 Feb 21 '14 at 22:47
  • 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 Feb 21 '14 at 22:51
  • 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): https://dl.dropboxusercontent.com/u/101534245/Instrument-Dump.trace.zip – Nathan Dunn Feb 21 '14 at 23:03
  • 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. https://dl.dropboxusercontent.com/u/101534245/Instruments-CoreData-Dump.trace.zip – Nathan Dunn Feb 22 '14 at 01:09

3 Answers3

0

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/

Duncan Groenewald
  • 8,496
  • 6
  • 41
  • 76
0

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

Jay
  • 6,572
  • 3
  • 37
  • 65
0

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.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • The fetching at launch is due to it re-opening the last document (it is a Document Based application). I can fix this specifically, but I'm still left with the issue that when it takes a long time to open files and the user is not given an indication that a file is being opened. – Nathan Dunn Feb 25 '14 at 13:08
  • it takes a long time to open files and the user is not given an indication that a file is being opened. `-getAllLoci` fetches all loci objects (upwards of 100K). `getMaxLocusSnps` ... calls `-getAllLoci`, extract NSData object off of each and extracts and does a simple cacluation (seeing a red flag!). – Nathan Dunn Feb 25 '14 at 13:09
  • `-getLociWithChromosomes` getsAllLoci with 2 predicates: SPredicate *predicate1 = [NSPredicate predicateWithFormat:@"chromosome != nil"]; NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"chromosome != ''"]; [request1 setPredicate:predicate1]; [request1 setPredicate:predicate2]; – Nathan Dunn Feb 25 '14 at 13:10
  • Sorry for the long delay in answer. This was the closest answer. There is definitely some speedup by doing a single query instead of a loop within the "Open Document" code. Thanks. – Nathan Dunn Mar 19 '14 at 18:50