Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreData performance about context saving

I finished converting my app to use the CoreData layer for a small datawarehouse I want to use. I have some concerns about the performance and how to best use it. In particular: I have a lot of runs where I read from disk attributes within files: each attribute should generate a new object, unless an object of that type and that value already exists. So, for each file I read, I: execute a fetch to check if that managed object already exists; if yes finish, otherwise I create the object, assign value and save context.

Currently, I save the context once for each time I create a new object, so it happens more or less ten times (for the ten attributes) for each file read (which can be hundreds). Would be better to reduce the context saving points, maybe once for file instead of once for attribute? I do not know the overhead of this operation so I don't know if is ok to do this so often, or how to find out the time spent on this (maybe with the instruments? Don't really know how).

like image 876
Andy Avatar asked Jan 16 '10 10:01

Andy


People also ask

What is context in Core Data?

From your perspective, the context is the central object in the Core Data stack. It's the object you use to create and fetch managed objects, and to manage undo and redo operations. Within a given context, there is at most one managed object to represent any given record in a persistent store.

Is realm better than Core Data?

Database usage. Working with Realm is much easier than with CoreData. The fact is that in order to use CoreData, you need a deep understanding of the API. In the case of Realm, everything is rather simpler.

Is Core Data thread safe?

Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.


2 Answers

There isn't any need to save after setting each attribute.

Normally, you only save a managed object when the code is done with it as saving resets the undo. In the set up you describe, you could safely generate hundreds of managed objects before saving them to permanent store. You can have a large number (thousands) of lightweight (text attributes) objects in memory without putting any strain on the iPhone.

The only problem on the iPhone is that you never know when the app will be suspended or shut down. This makes saves more common than on other platforms. However, not to the extent you now use.

Core Data Performance section of the guide might help you plan. Instruments allows you to see the details of Core Data performance.

However, I wouldn't do anything until you've tested the app with a great deal of data and found it slow. Premature optimization is the source of all evil. Don't waste time trying to prevent a problem you may not have.

like image 153
TechZen Avatar answered Oct 05 '22 22:10

TechZen


To prevent a "sudden application stop" problem you can implement something like that method:

- (void)saveContext {

NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;


if (managedObjectContext != nil) {
    if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        LogError(@"Unresolved error %@, %@", error, [error userInfo]);
            // abort();
    } 
}

}

and use it inside two methods of your app delegate:

- (void)applicationWillTerminate:(UIApplication *)application;

and

- (void)applicationDidEnterBackground:(UIApplication *)application;

Thought it may not be the 100% solution, but in most of the cases it will do the work...

like image 23
Ariel Avatar answered Oct 06 '22 00:10

Ariel