Swift中大量Core Data批处理插入的内存泄漏 [英] Memory leak with large Core Data batch insert in Swift
问题描述
我在核心数据实体中插入了数以万计的对象。我有一个 NSManagedObjectContext
,我每次添加一个对象时,在托管对象上下文中调用 save()
。它工作,但它正在运行时,内存不断从约27M增加到400M。
有关批次插入的一些SO问题,每个人都说要阅读
进一步阅读
- 高效地导入数据(旧的苹果文档链接被破坏如果你能找到它,请帮助我添加它。)
- Core Data Performance
- 核心数据(大会帖子)
上面的答案是完全改写的。感谢@Mundi和@MartinR在评论中指出我的原始答案中的错误。感谢@JodyHagins在此答案中帮助我理解和解决问题。
I am inserting tens of thousands of objects into my Core Data entity. I have a single NSManagedObjectContext
and I am calling save()
on the managed object context every time I add an object. It works but while it is running, the memory keeps increasing from about 27M to 400M. And it stays at 400M even after the import is finished.
There are a number of SO questions about batch insert and everyone says to read Efficiently Importing Data, but it's in Objective-C and I am having trouble finding real examples in Swift that solve this problem.
There are a few things you should change:
- Create a separate
NSPrivateQueueConcurrencyType
managed object context and do your inserts asynchronously in it. - Don't save after inserting every single entity object. Insert your objects in batches and then save each batch. A batch size might be something like 1000 objects.
- Use
autoreleasepool
andreset
to empty the objects in memory after each batch insert and save.
Here is how this might work:
let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator // or wherever your coordinator is
managedObjectContext.performBlock { // runs asynchronously
while(true) { // loop through each batch of inserts
autoreleasepool {
let array: Array<MyManagedObject>? = getNextBatchOfObjects()
if array == nil { break }
for item in array! {
let newEntityObject = NSEntityDescription.insertNewObjectForEntityForName("MyEntity", inManagedObjectContext: managedObjectContext) as! MyManagedObject
newObject.attribute1 = item.whatever
newObject.attribute2 = item.whoever
newObject.attribute3 = item.whenever
}
}
// only save once per batch insert
do {
try managedObjectContext.save()
} catch {
print(error)
}
managedObjectContext.reset()
}
}
Applying these principles kept my memory usage low and also made the mass insert faster.
Further reading
- Efficiently Importing Data (old Apple docs link is broken. If you can find it, please help me add it.)
- Core Data Performance
- Core Data (General Assembly post)
Update
The above answer is completely rewritten. Thanks to @Mundi and @MartinR in the comments for pointing out a mistake in my original answer. And thanks to @JodyHagins in this answer for helping me understand and solve the problem.
这篇关于Swift中大量Core Data批处理插入的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!