2012-11-02 32 views
9

हम एंटरप्राइज़-स्तरीय एप्लिकेशन पर काम कर रहे हैं, जो कोर डेटा के साथ हजारों ऑब्जेक्ट्स स्टोर करेगा, और हमें कई मोर्चों पर समस्याएं हैं।कोर डेटा प्रबंधित ऑब्जेक्ट संदर्भ डिजाइन अनुशंसा


हमारे एप्लिकेशन में कई स्वतंत्र सिस्टम हैं जो आवश्यक होने पर डेटा पर काम करते हैं। इन प्रणालियों में वस्तुओं की खोज, वस्तुओं की लोडिंग, सिंक्रनाइज़ेशन और यूआई डिस्प्ले शामिल हैं। यदि हम अपने सॉफ़्टवेयर को सही तरीके से डिज़ाइन करते हैं, तो अलग-अलग सिस्टमों को संशोधित करने वाले विभिन्न सिस्टमों के कारण विवादों को मर्ज करने के लिए बहुत कम होना चाहिए। प्रत्येक प्रणाली में अपनी खुद की ऑपरेशन कतार होती है, जो पृष्ठभूमि में प्रदर्शन करती हैं। हम UI प्रदर्शन समस्याओं को कम करने के लिए पृष्ठभूमि में सभी ऑब्जेक्ट सृजन और संशोधन को रखना चाहते हैं, खासकर प्रारंभिक रैंप अप के दौरान, जहां सर्वर पर डेटा से हजारों ऑब्जेक्ट्स बनाए जा सकते हैं। यहां हमने अपने विभिन्न डिजाइन प्रयासों के साथ कई समस्याएं निभाई हैं। इन रैंप अप के दौरान बड़ी मेमोरी खपत, और सभी संदर्भों और बाल संदर्भों के गलत ऑर्केस्ट्रेशन, जिससे डेडलॉक्स और क्रैश होते हैं। NSPrivateQueueConcurrencyType प्रबंधित वस्तु संदर्भ में जो एक बच्चे NSMainQueueConcurrencyType संदर्भ है

  • एक जड़: हम निम्नलिखित डिजाइन प्रयास किया है। यूआई प्राप्त परिणाम नियंत्रक परिणाम प्राप्त करने के लिए इस बच्चे के संदर्भ का उपयोग करते हैं। NSMainQueueConcurrencyType बाल संदर्भ से, हमने एक NSPrivateQueueConcurrencyType बाल संदर्भ बनाया, जिसे हमने "saveContext" कहा था और प्रत्येक पृष्ठभूमि ऑपरेशन ने उस "बचत कोटेक्स्ट" का एक बाल संदर्भ बनाया, इसके परिवर्तन हुए, और आखिरकार हमने "गहरी बचत" कहा, जिसे हम दोहराते हैं शीर्ष पर बचत। हमने शुरुआत में इस डिजाइन को कई अलग-अलग बाल संदर्भों से NSManagedObjectContextDidSaveNotification अधिसूचनाओं से निपटने के लिए नहीं चुना है। हमने प्रत्येक कॉल को NSPrivateQueueConcurrencyType संदर्भों और performBlockAndWait: के साथ ऑब्जेक्ट तक पहुंचने के लिए लपेट लिया। कार्यात्मक रूप से, इस डिजाइन प्रदर्शन किया। सभी परिवर्तन और आवेषण लगातार स्टोर में सहेजे गए थे, और यूआई को परिवर्तनों के साथ अपडेट किया गया था। इसने दो मुद्दों की शुरुआत की। NSMainQueueConcurrencyType बाल संदर्भ के माध्यम से विलय किए गए परिवर्तनों के कारण रैंप अप के दौरान एक लगी यूआई था, और अधिक महत्वपूर्ण बात यह है कि रैंप अप के दौरान बहुत अधिक मेमोरी उपयोग होता है। पर कॉल करने के दौरान संदर्भों पर पुनरावर्ती रूप से reset पर कॉल करने में असमर्थता के कारण हम निषिद्ध RAM उपयोगों को प्रभावित करेंगे (क्योंकि मुख्य यूआई बाल संदर्भ भी है) और/या ज्ञान की कमी के समय refreshObject:mergeChanges: पर कॉल करें। तो हम एक अलग सड़क चले गए।
  • यूआई डिस्प्ले के लिए लगातार स्टोर समन्वयक, NSPrivateQueueConcurrencyType और यूआई डिस्प्ले के लिए NSMainQueueConcurrencyType के साथ जुड़े दो शीर्ष-स्तरीय संदर्भ हैं। NSMainQueueConcurrencyType मुख्य NSPrivateQueueConcurrencyType संदर्भ से NSManagedObjectContextDidSaveNotification सूचनाओं को सुनता है और उन्हें मुख्य धागे में विलीन करता है। प्रत्येक पृष्ठभूमि ऑपरेशन मुख्य NSPrivateQueueConcurrencyType संदर्भ का एक बाल संदर्भ बनाता है, निजी कतार समरूपता प्रकार के साथ भी, जो करता है, वह "गहरी बचत" करता है, जो वर्तमान संदर्भ पर सहेजता है, इसकी गहरी बचत की एक पुनरावर्ती कॉल अभिभावक, वर्तमान संदर्भ पर रीसेट कॉल करता है और फिर से बचाता है। इस तरह हम स्मृति समस्याओं से बचते हैं, क्योंकि सहेजे गए सामानों को सहेजने के तुरंत बाद जारी किया जाता है। हालांकि, इस डिज़ाइन के साथ, हमने NSMainQueueConcurrencyType संदर्भ के लिए अधिसूचनाओं को सहेजने के बावजूद मृत ताले, NSInternalInconsistencyException अपवादों जैसे मुद्दों को प्राप्त किया है और यूआई को अपडेट नहीं किया है। यह यूआई में बहुत धीमा करने के लिए शुरुआती लोड समय भी पैदा करता है। पिछले डिज़ाइन में, प्राप्त किए गए परिणाम नियंत्रक ने परिणाम बहुत तेज़ कर दिए, जबकि यूआई ने दृश्य लोड होने तक कई सेकंड तक अवरुद्ध कर दिया है (हम viewDidLoad में प्राप्त परिणाम नियंत्रक प्रारंभ करते हैं)।

हम कई मध्यवर्ती डिजाइन की कोशिश की है, लेकिन वे सभी एक ही मुद्दों के चारों ओर घूमना, या तो बहुत अधिक स्मृति उपयोग, प्राप्त किए गए परिणाम नियंत्रक यूआई या गतिरोध और NSInternalInconsistencyException अपवाद अपडेट नहीं हो।


मैं वास्तव में निराश हो रहा हूं। मैं ऐसा महसूस नहीं कर सकता जैसे कि हमारे डिजाइन किसी चीज के लिए अत्यधिक जटिल हैं जो कि सरल होना चाहिए, और यह हमें कुछ मौलिक समझने की कमी है जो हमें मार रहा है।


तो आप लोग क्या सुझाव देंगे? आप हमारे संदर्भों के लिए किस व्यवस्था की सिफारिश करेंगे? हमें विभिन्न धागे में विभिन्न संदर्भों का प्रबंधन कैसे करना चाहिए? सम्मिलित वस्तुओं को मुक्त करने और संदर्भों को रीसेट करने के लिए सर्वोत्तम अभ्यास? मृत ताले से बचना? इस बिंदु पर सभी मदद की सराहना की जाएगी।


मैंने मैजिकल रिकॉर्ड्स श्रेणी के लिए भी सिफारिशें देखी हैं। क्या इसकी सिफारिश की जाती है? हम कोर डेटा प्रकारों का उपयोग करने में पहले ही निवेश कर चुके हैं, एमआर का उपयोग करके माइग्रेट करना कितना मुश्किल होगा?

+0

मुझे समान समस्याएं हैं (आर्किटेक्चर एक): http://stackoverflow.com/questions/15999932/core-data-break-retain-cycle-of-the-parent-context/16008470 - किस तरह का आर्किटेक्चर क्या आप अंत में गए थे? कोई सुझाव? – Zyphrax

+0

हमारे पास एक मुख्य संदर्भ और मूल रूट संदर्भ है। लेकिन मूल संदर्भ केवल सहेजने के लिए उपयोग किया जाता है, इसलिए हम इसे प्रत्येक सहेजने पर रीसेट करते हैं। हमारे पास असंख्य मुद्दे हैं। ऐसा लगता है कि बच्चे और माता-पिता के संदर्भों की इन नई विशेषताओं को अच्छी तरह से सोचा नहीं गया है और ऐप्पल द्वारा अभी भी कई बग्स अनुपस्थित हैं। –

+0

मैं एक बच्चे एमओसी (मेनक्यूयू) के साथ रूट एमओसी (प्राइवेट क्यूयू) के साथ आर्किटेक्चर की तरफ झुका रहा हूं और ''' [self.managedObjectContext refreshObject: self mergeChanges: NO]; '' '' ' मेरे कुछ प्रबंधित ऑब्जेक्ट्स में '-डिडसेव'''। यह संबंधों के बीच बनाए रखने के चक्र को अलग करता है और सभी एमओसी वस्तुओं को हटाने की इजाजत देता है। NSPrivateQueueConcurrencyType के साथ केवल एमओसी एक अजीब मुद्दा प्रतीत होता है कि वे तुरंत ऑब्जेक्ट्स को डिलीकेट नहीं करेंगे बल्कि अगली बचत/रोलबैक पर। – Zyphrax

उत्तर

6

सबसे पहले, अपनी याददाश्त का प्रबंधन करने के लिए, आपका दूसरा आर्किटेक्चर आपको अधिक लचीलापन देता है।

दूसरा, प्रबंधन के लिए दो प्रकार की मेमोरी है: malloc-ed स्मृति और निवासी वीएम मेमोरी। आपके पास कम मॉलोक-एड मेमोरी पदचिह्न हो सकता है और अभी भी एक बड़ा वीएम निवासी क्षेत्र है। यह मेरे अनुभव में, कोर डेटा को आक्रामक रूप से नए डालने वाले आइटमों पर रखने के कारण है। मैं इस समस्या को एक पोस्ट-सेव ट्रिमिंग अधिसूचना के साथ हल करता हूं।

तीसरा, एमओसी सस्ते हैं। उपयोग करें और फेंक दें। दूसरे शब्दों में, जल्दी और अक्सर स्मृति जारी करें।

चौथा, मुख्य एमओसी पर डेटा आधार के अनुसार लगभग कुछ भी करने की कोशिश करें। हां, यह काउंटर-उत्पादक लगता है। मेरा मतलब यह है कि आपके सभी जटिल प्रश्नों को पृष्ठभूमि धागे पर वास्तव में किया जाना चाहिए और फिर परिणाम मुख्य धागे में पास हो गए हैं या अब मुख्य आबादी से प्रश्नों को फिर से तैयार किया गया है जबकि अब आबादी वाले पंक्ति-कैश का शोषण किया जा रहा है। ऐसा करके, आप UI को लाइव रखते हैं।

पांचवें, मेरे भारी बहु-पंक्तिबद्ध ऐप में, मैं अपने सभी बचत वास्तव में पृष्ठभूमि में होने का प्रयास करता हूं। यह मेरा मुख्य एमओसी नेट से आने वाले डेटा के साथ तेज़ और सुसंगत रहता है।

छठी, NSFetchedResultsController एक काफी उपयोगी लेकिन विशेष नियंत्रक है। यदि आपका एप्लिकेशन इसे सक्षमता के क्षेत्र के बाहर धक्का देता है, तो यह आपके इंटरफ़ेस को लॉक करना शुरू कर देता है। जब ऐसा होता है, तो मैं -डिडसेव अधिसूचनाओं को स्वयं सुनकर अपना स्वयं का नियंत्रक रोल करता हूं।

+0

आपके उत्तर के लिए धन्यवाद! लॉक अप के बारे में क्या? वर्तमान में, हमारे ऐप समय-समय पर लॉक हो जाते हैं, जो कारण हमारे लिए अस्पष्ट हैं। अधिसूचना के बाद 'mergeChangesFromContextDidSaveNotification: 'को कॉल करते समय यह आमतौर पर लॉक हो जाता है। क्या कई धागे एक ही समय में बचा सकते हैं? संदर्भों को बंद कर दिया जाना चाहिए? –

+0

लियो, मैं उस समय को कम करता हूं जब मेरा यूआई मुख्य एमओसी में लॉक हो जाता है, इससे कोई भी बदलाव कभी भी सहेजने की कोशिश नहीं करता है। अर्थात। नया डेटा पृष्ठभूमि से इसमें विलीन हो जाता है। यह मुख्य एमओसी मुक्त रखता है। साथ ही, यह देखने के लिए जांच करें कि लॉक अप है क्योंकि आप अपने fetched परिणाम नियंत्रक को अपडेट कर रहे हैं या बस एमओसी विलय कर रहे हैं। (मैं पूर्व शर्त लगा रहा हूं। आप एफआरसी प्रतिनिधि को स्थापित न करके परीक्षण कर सकते हैं।) हां, कई धागे एक ही समय में बचा सकते हैं। चूंकि SQLite एक सिंगल थ्रेडेड स्टोर है, सबकुछ पीएससी के माध्यम से क्रमबद्ध होता है - यह भी पढ़ता है। नतीजतन, मैं अपने लेखन एमओसी के माध्यम से अपने लिखने/बचाता है। एंड्रयू – adonoho