iOS 18.2, Swift, Xcode 16.2
I have a Core Data model with two entities - WarehouseArea (of which there is only one object) and StockReeipt (of which there are a couple of hundred thousand). Each StockReceipt must be linked to a WarehouseArea, and a WarehouseArea can be linked to zero, one or many StockReceipts.
My problem is that when I create and add one more StockReceipt, the Core Data save takes over 3 seconds to complete. I don't understand why this is so slow. Saving the initial 200,000 StockReceipts only takes 5-6 seconds.
When I enable SQL logging I can see that when the WarehouseArea attribute is being set on a StockReceipt, Core Data fetches all of the other StockReceipts (I don't know why) but that only takes 0.2 seconds and none of those StockReceipts are modified, so there shouldn't be any need to process them when saving the context.
I have prepared a test project which can be found at https://github.com/DaleReilly/CoreDataSaveTester . Running the project will produce NSLog output showing the times before and after the slow save.
Please help me understand what is going on in the background and tell me if there is any way I can speed this up?
From your project, I see that you are using a nested context:
let pscMoc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
pscMoc.persistentStoreCoordinator = persistentStoreCoordinator
let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
moc.parent = pscMoc
Is there any strong reason that you need a parent context in between your main context and the persistent store coordinator? If not, I'd suggest that you avoid doing that, because to support a nested context, Core Data needs to do more work to coordinate the data saving and fetching:
//moc.parent = pscMoc
moc.persistentStoreCoordinator = persistentStoreCoordinator
With this simple change, you get a significantly better performance, as shown in the following log:
- Before (around 2.55s / 1.05s)
Saving 200,000 receipts at 2025-01-24 16:14:06.3430
Finished saving 200,000 receipts at 2025-01-24 16:14:08.8920
Saving one more receipt at 2025-01-24 16:14:08.8970
Finished saving one receipt at 2025-01-24 16:14:09.9480
- After (around 1.08s / 0.03s)
Saving 200,000 receipts at 2025-01-24 16:14:51.6010
Finished saving 200,000 receipts at 2025-01-24 16:14:52.6870
Saving one more receipt at 2025-01-24 16:14:52.6920
Finished saving one receipt at 2025-01-24 16:14:52.7200
Best,
——
Ziqiao Chen
Worldwide Developer Relations.