Swift 中的大型 Core Data 批量插入导致内存泄漏

Memory leak with large Core Data batch insert in Swift

我正在将数万个对象插入到我的核心数据实体中。我有一个 NSManagedObjectContext,每次添加对象时我都会在托管对象上下文上调用 save()。它可以工作,但是当它是 运行 时,内存从大约 27M 增加到 400M。而且导入完成后还是400M

有很多关于批量插入的 SO 问题,每个人都说要阅读 Efficiently Importing Data,但它在 Objective-C 中,我无法在 Swift 中找到真正的例子来解决这个问题。

您应该更改一些内容:

  • 创建一个单独的 NSPrivateQueueConcurrencyType 托管对象上下文并在其中异步插入。
  • 插入每个实体对象后不保存。分批插入对象,然后保存每批。批量大小可能类似于 1000 个对象。
  • 使用autoreleasepoolreset在每次批量插入和保存后清空内存中的对象。

这可能是这样工作的:

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()
    }
}

应用这些原则使我的内存使用率保持在较低水平,并使批量插入速度更快。

进一步阅读

更新

以上答案完全重写。感谢评论中的@Mundi 和@MartinR 指出我原来答案中的错误。并感谢 中的@JodyHagins 帮助我理解和解决问题。