Swift 中大量 Core Data 批量插入的内存泄漏
Posted
技术标签:
【中文标题】Swift 中大量 Core Data 批量插入的内存泄漏【英文标题】:Memory leak with large Core Data batch insert in Swift 【发布时间】:2015-11-09 03:05:18 【问题描述】:我将数以万计的对象插入到我的核心数据实体中。我有一个NSManagedObjectContext
,每次添加对象时我都会在托管对象上下文上调用save()
。它可以工作,但是在运行时,内存不断从大约 27M 增加到 400M。并且导入完成后也保持在400M。
有很多关于批量插入的 SO 问题,每个人都说要阅读 Efficiently Importing Data,但它是在 Objective-C 中的,我很难在 Swift 中找到解决这个问题的真实示例。
【问题讨论】:
【参考方案1】:有几件事你应该改变:
创建一个单独的NSPrivateQueueConcurrencyType
托管对象上下文并在其中异步插入。
插入每个实体对象后不要保存。分批插入对象,然后保存每个批次。批量大小可能是 1000 个对象。
每次批量插入并保存后,使用autoreleasepool
和reset
清空内存中的对象。
这是如何工作的:
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 newObject = 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()
应用这些原则使我的内存使用率保持在较低水平,同时也使批量插入速度更快。
进一步阅读
高效导入数据(旧 Apple 文档链接已损坏。如果您能找到,请帮我添加。) Core Data Performance Core Data(大会发帖)更新
上面的答案完全重写了。感谢 cmets 中的 @Mundi 和 @MartinR 指出我原始答案中的一个错误。并感谢this answer 中的@JodyHagins 帮助我理解和解决问题。
【讨论】:
您的代码中似乎使用的是相同的托管对象上下文,而不是新的。 在我上面的示例中,每个while
循环都会重新创建托管对象上下文。 while
循环代表一批插入,因此单个批次使用相同的托管对象上下文,但下一批会创建一个新的。我过去的问题是我将上下文设为类属性并且从未更改过它。
@Suragch:这取决于managedObjectContext
属性是如何在应用程序委托中实现的,但“通常”的实现是一个惰性属性,它在应用程序的生命周期内创建一次上下文。在这种情况下,您将重用与 Mundi 所说的相同的上下文。
我想进一步了解这些 cmets 的含义,所以我开了一个新问题:Where should NSManagedObjectContext be created?
太棒了——除了自动释放池,我什么都有。谢谢。以上是关于Swift 中大量 Core Data 批量插入的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
IOS - 如何在 Core Data Swift 中将数据插入到具有关系的不同表中
在Core Data中,如何在swift 4中执行`if exists update else insert`? [复制]