3lvis / DATAStack

100% Swift Simple Boilerplate Free Core Data Stack. NSPersistentContainer
Other
214 stars 44 forks source link

fetchBatchSize ignored while using DATAStack.mainContext in NSFRC #59

Closed zarv1k closed 8 years ago

zarv1k commented 8 years ago

I use DATASource for showing large (~50000 rows) data set and using DATAStack.mainContext in NSFRC. When I set request.fetchBatchSize for optimizing memory usage purposes it is ignored somehow. And all 50000 rows loads into memory.

I research for the issue a little bit and found that there is an issue in Core Data when stack configured with usage of nested contexts. - http://openradar.appspot.com/11235622. Also here is what I found on StackOverflow

May be some workaround can be implemented in DATAStack for partially resolve the described issue. For example, DATAStack could provide so called newMainContext() method that should return context that have NSMainQueueConcurencyType and directly linked to Persistent Store Coordinator. Another possible solution (not sure about that): try to use background context in NSFRC that newBackgroundContext() method can return. But in this case this context should be notified about changes in persistent store that have been done in another background context and merge them for update table in UI.

Have you any thoughts about that? Thank you

3lvis commented 8 years ago

Hi, I did some profiling with my test project loading 62 700 rows.

https://github.com/3lvis/SyncPerformance

No batch size, current stack

screen shot 2016-05-15 at 13 43 23

Batch size, current stack

screen shot 2016-05-15 at 13 47 53

Batch size, modified stack to make mainContext not use parentContext

screen shot 2016-05-15 at 13 40 36
/**
 The context for the main queue. Please do not use this to mutate data, use `performInNewBackgroundContext`
 instead.
 */
public var mainContext: NSManagedObjectContext {
    get {
        if _mainContext == nil {
            let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
            context.undoManager = nil
            context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
            context.persistentStoreCoordinator = self.persistentStoreCoordinator

            NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DATAStack.mainContextDidSave(_:)), name: NSManagedObjectContextDidSaveNotification, object: context)

            _mainContext = context
        }

        return _mainContext!
    }
}
3lvis commented 8 years ago

@zarv1k could you verify if by making this change locally things actually improve on your side?

https://github.com/3lvis/DATAStack/pull/60

zarv1k commented 8 years ago

@3lvis I was made the exactly same changes before I had created this ticket. But I was not sure that such changes should be applied, because many other core data wrapper libraries are set up the main context in stack using parent/child pattern (open issue in MagicalRecord for example). However I just checked again and confirm that this changes improve memory usage and fetchBatchSize became work as expected.

3lvis commented 8 years ago

Cool! I'm glad this is fixed :)

3lvis commented 8 years ago

https://github.com/3lvis/DATAStack/releases/tag/5.2.1 Released 💥