2015-08-16 16 views
8

我將數以萬計的對象插入到我的Core Data實體中。我有一個單獨的NSManagedObjectContext,並且每次添加對象時我都會在託管對象上下文中調用save()。它可以工作,但在運行時,內存從大約27M增加到400M。即使導入完成後,它仍然保持在400M。在Swift中使用大型Core Data批量插入的內存泄漏

enter image description here

有一些關於批量插入和大家做題說,讀Efficiently Importing Data,但它在Objective-C和我無法找到斯威夫特是解決這個問題的真實案例。

回答

15

有一些事情你應該改變:

  • 創建一個單獨的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 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() 
    } 
} 

應用這些原則一直在我的內存使用量低,也讓大衆插入更快。

enter image description here

進一步閱讀

  • 高效導入數據(老蘋果文檔的鏈接被打破了。如果你能找到它,請幫我添加它。)
  • Core Data Performance
  • Core Data(大會帖子)

更新

以上回答被完全重寫。感謝@Mundi和@MartinR在評論中指出我原來的答案中有錯誤。並感謝@JodyHagins在this answer幫助我理解和解決問題。

+1

在您的代碼中,您似乎使用的是相同的託管對象上下文,而不是新的託管對象上下文。 – Mundi

+0

在我上面的示例中,每個'while'循環都會重新創建託管對象上下文。 while循環表示一批插入,因此一個批處理使用相同的託管對象上下文,但下一批創建一個新的插入。我過去的問題是,我將上下文作爲類屬性,從不改變它。 – Suragch

+1

@Suragch:這取決於如何在Application委託中實現'managedObjectContext'屬性,但是「常規」實現是一個lazy屬性,它在應用程序的生命週期中創建一次上下文。在這種情況下,你正在重複使用與Mundi所說的相同的上下文。 –