Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data Inferred Migration – Automatic "lightweight" vs Manual

I've updated the model of an existing iPhone app in some simple ways (remove attribute, add attribute, remove index), and can use automatic lightweight migration to migrate the persistent store.

Due to the typical size of the data set, the processing time is not insignificant, and warrants feedback for the user.

NSMigrationManager provides a simple but useful migrationProgress value that sends KVO notifications as the migration is performed. That forms the basis of providing feedback, however attempting to use an inferred model ([NSMappingModel inferredMappingModelForSourceModel:destinationModel:error:]) results in drastically different timing for the exact same dataset.

Profile results on an original iPhone (2G), Cache size: 1.785 MB on disk.

Automatic inferred lightweight migration

PROFILE: CacheManager -migrateStore
PROFILE:   0.6130 (+0.6130) models loaded
PROFILE:   1.1759 (+0.5629) delegate -CacheManagerWillMigrate:
PROFILE:   1.2516 (+0.0757) persistent store coordinator loaded
PROFILE:   5.1436 (+3.8920) automatic lightweight migration completed
PROFILE:   5.5435 (+0.3999) delegate -CacheManagerDidFinishMigration:withError:

Manual inferred migration

PROFILE: CacheManager -migrateStore
PROFILE:   0.6660 (+0.6660) models loaded
PROFILE:   1.1471 (+0.4811) inferred mapping model generated
PROFILE:   1.4046 (+0.2574) delegate -CacheManagerWillMigrate:
PROFILE:   1.5058 (+0.1013) persistent store coordinator loaded
PROFILE:   22.6952 (+21.1894) manual migration completed
PROFILE:   23.1478 (+0.4525) delegate -CacheManagerDidFinishMigration:withError:

So, with an inferred model, the manual migration takes over 5 times longer than automatic!


UPDATE: Model loading

Core Data documentation for NSPersistentStoreCoordinator "Migration Options" says:

NSInferMappingModelAutomaticallyOption

... the coordinator will attempt to infer a mapping model if none can be found.

And that is why the XCode built,compiled & bundled mapping model has to be removed (or just un-targetted) to allow an inferred and lightweight migration to happen.


It's a big inconsistency, and the lightweight option that NSPersistentStoreCoordinator -addPersistentStoreWithType:configuration:URL:options:error: provides absolutely no indication of progress while processing.

Can anybody provide a supported way to get the migrationProgress values during automatic migration, OR a way to configure an inferred mapping model to be as fast during manual processing as automatic?


UPDATE: Bug Report

Spoke to the engineers at WWDC and they've asked for a bug report requesting the migrationProgress for the automatic lightweight migration processing.

I'll update again if the API is updated to add progress reporting..

like image 907
ohhorob Avatar asked Mar 29 '10 01:03

ohhorob


People also ask

What is lightweight migration?

Core Data can typically perform an automatic data migration, referred to as lightweight migration. Lightweight migration infers the migration from the differences between the source and the destination managed object models.

What is heavy weight migration IOS?

A migration manager instance that performs a migration of data from one persistent store to another using a given mapping model. class NSMappingModel. A model instance that specifies how to map a model from a source to a destination managed object model.

What is heavy weight migration?

We perform heavyweight migration when we have either normalized or generalized our database. In such cases, lightweight migration won't help us. We will have to manually map attributes of the old data model to the new data model, and doing so is called heavyweight migration.

How to migrate Core Data model?

Migrations happen in three steps: First, Core Data copies over all the objects from one data store to the next. Next, Core Data connects and relates all the objects according to the relationship mapping. Finally, enforce any data validations in the destination model.


1 Answers

Currently Core Data uses a private class, NSSQLiteInPlaceMigrationManager, to perform lightweight migration. This is a subclass of NSMigrationManager, but handles everything itself in migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:. From the looks of it, this class is actually performing alterations directly on the SQLite store instead of pulling everything into memory as required by manual migration.

This explains why you're seeing the lightweight migration complete much faster.

Unfortunately, even if you use this knowledge of the private APIs that are being used behind the scenes, it doesn't gain you much for getting a progress indication. The value of progress is currently never changed for NSSQLiteInPlaceMigrationManager, it's always zero. The value of currentEntityMapping also seems to remain nil.

Until Apple provides an API, it seems we're out of luck. Do you have a radar number so I can open a duplicate?

like image 198
wbyoung Avatar answered Sep 28 '22 21:09

wbyoung