2015-08-16 8 views
8

में बड़े कोर डेटा बैच डालने के साथ मेमोरी लीक मैं अपनी कोर डेटा इकाई में हजारों ऑब्जेक्ट्स डाल रहा हूं। मेरे पास एक NSManagedObjectContext है और मैं ऑब्जेक्ट जोड़ने पर प्रबंधित ऑब्जेक्ट संदर्भ पर save() पर कॉल कर रहा हूं। यह काम करता है लेकिन यह चल रहा है, जबकि स्मृति लगभग 27 एम से 400 मीटर तक बढ़ती रहती है। और आयात समाप्त होने के बाद भी यह 400 मीटर पर रहता है।स्विफ्ट

enter image description here

अतः बैच डालने और हर किसी के बारे में कई सवाल Efficiently Importing Data पढ़ने के लिए कहते हैं कर रहे हैं, लेकिन यह ऑब्जेक्टिव-सी में है और मैं दिक्कत यह है कि इस समस्या को हल स्विफ्ट में वास्तविक उदाहरण खोजने हो रहा है।

उत्तर

15

कुछ चीजें आप बदलना चाहिए:

  • एक अलग 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 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 के लिए धन्यवाद। और समस्या को समझने और हल करने में मेरी सहायता के लिए this answer में @ जॉडी हैगिन के लिए धन्यवाद।

+1

ऐसा लगता है कि आप अपने कोड में एक ही प्रबंधित ऑब्जेक्ट संदर्भ का उपयोग कर रहे हैं, न कि एक नया। – Mundi

+0

प्रबंधित ऑब्जेक्ट संदर्भ उपरोक्त मेरे उदाहरण में प्रत्येक 'जबकि' लूप पर फिर से बनाया जाता है। 'While' लूप आवेषण के एक बैच का प्रतिनिधित्व करता है, इसलिए एक बैच एक ही प्रबंधित ऑब्जेक्ट संदर्भ का उपयोग करता है, लेकिन अगला बैच एक नया बनाता है। अतीत में मेरी समस्या यह थी कि मैंने संदर्भ को एक वर्ग संपत्ति बना दी और इसे कभी नहीं बदला। – Suragch

+1

@Suragch: यह इस बात पर निर्भर करता है कि 'प्रबंधित ऑब्जेक्ट कॉन्टेक्स्ट' संपत्ति एप्लिकेशन प्रतिनिधि में कैसे कार्यान्वित की जाती है, लेकिन "सामान्य" कार्यान्वयन एक आलसी संपत्ति है जो ऐप के जीवनकाल के लिए एक बार संदर्भ बनाता है। उस मामले में आप उसी संदर्भ का पुन: उपयोग कर रहे हैं क्योंकि मुंडी ने कहा था। –