2012-09-06 17 views
9

मुझे यह समस्या है। मेरे पास कोर डेटा में छवियों का डेटाबेस है। मैं सभी छवियों (लगभग 80 एमबी) लाता हूं और एक एनएसएमयूटेबलएरे में डालता हूं। वस्तुओं को सही ढंग से गलती कर रहे हैं:कोर डेटा मेमोरी उपयोग और मेमोरी चेतावनी

NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:request error:&error]; 
self.cache = [NSMutableArray arrayWithArray:fetchResults]; 
for (ImageCache *imageObject in self.cache) { 
    NSLog(@"Is fault? %i", [imageObject isFault]); 
} 

लॉग पढ़ना, मुझे लगता है कि वस्तुओं सब सही ढंग से हालांकि गलती कर रहे हैं, उपकरण का उपयोग कर, मुझे लगता है कि स्मृति के 80MB किया जाता है। मुझे लगता है कि यही कारण है कि कोर डेटा इसके परिणामों को कैश करता है, और इसकी आवश्यकता होने पर स्मृति को मुक्त करना चाहिए। लेकिन (और यह मेरी "समस्या" है), अगर मैं स्मृति चेतावनी अनुकरण करता हूं, तो कुछ भी नहीं होता! 80 एमबी वहां बनी हुई है। (उदाहरण)

ग्राफ़ श्रेणी लाइव बाइट्स # लिविंग # क्षणभंगुर कुल मिलाकर बाइट्स # कुल मिलाकर # आवंटन (नेट/कुल मिलाकर) 0 Malloc 176,00: -

उपकरणों को देखते हुए आवंटन, 80MB कई Malloc द्वारा किया जाता है केबी 8,59 एमबी 50 57 18,39 एमबी 107% 0.00,% 0.00 0 मॉलोक 200,00 केबी 8,20 एमबी 42 460 98,05 एमबी 502% 0.00,% 0.04 0 मॉलोक 168,00 केबी 7,05 एमबी 43 19 10,17 एमबी 62% 0.00% 0.00

इस पूरी कॉल ट्री की एक छवि के लिए एक लिंक है: https://www.dropbox.com/s/du1b5a5wooif4w7/Call%20Tree.png

कोई विचार? धन्यवाद

+0

शायद कोर डेटा मेमोरी चेतावनी स्तर 2 पर स्मृति को मुक्त करता है? क्या आपके परिदृश्य के साथ कम मेमोरी क्रैश उत्पन्न करना संभव है? – brigadir

+0

क्या मेमोरी चेतावनी स्तर 2 अनुकरण करने के लिए कोई "जादू विधि" है? या "बस" मुझे स्मृति का उपभोग करना है? – LombaX

+0

मुझे कोई सिमुलेशन विधि नहीं पता है। आपको एक और "भारी" ऐप (उदाहरण के लिए ऐपस्टोर) चलाएं, अपने ऐप को पृष्ठभूमि में रखें और कंसोल लॉग और इंस्ट्रूमेंट्स मेमोरी चार्ट को ट्रैक करना चाहिए। कंसोल में 'स्तर 2' चेतावनी का उल्लेख किया जाएगा - इसलिए आपको उस पल में मेमोरी चार्ट देखना चाहिए। – brigadir

उत्तर

9

ठीक है, मुझे समझ में आया कि ऐसा क्यों होता है। जब आप किसी इकाई के लिए फ़ेच अनुरोध करते हैं, भले ही गलती सक्षम हो, तो उस इकाई का सभी डेटा स्मृति में लोड हो जाता है। बड़े बाइनरी डेटा सहित।

1- आपके NSFetchRequest इस सेटिंग: आप इस का उपयोग कर कई तरीके हल कर सकते हैं [request setIncludesPropertyValues:NO]; की स्थापना नहीं, डेटा कैश में तुरंत लोड नहीं कर रहे हैं, लेकिन केवल अनुरोध पर (जब आप संपत्ति का उपयोग और गलती है निकाल दिया गया) लेकिन इसमें "समस्या" है। भले ही आप दोबारा प्रस्ताव को गलती करने का प्रयास करें (क्योंकि आपको तुरंत इसकी आवश्यकता नहीं है और [self.managedObjectContext refreshObject:object mergeChanges:NO]; का उपयोग करके स्मृति को मुक्त करना चाहते हैं), स्मृति मुक्त नहीं होती है। प्रबंधित ओब्जेक्ट कॉन्टेक्स्ट रीसेट होने तक कैश जीवित रहेगा।

यह बेहतर है:

2- आप अलग संस्थाओं में अपने डेटा को विभाजित कर सकते हैं। मेरे मामले में मेरे पास केवल 2 गुण थे: एक यूआरएल और छवि डेटा। मैंने डेटा को 1 इकाइयों में 1: 1 रिश्ते के साथ विभाजित किया: imagecache और imagedata। "imagecache" इकाई (यूआरएल प्रॉपर्टी के साथ) की सभी पंक्तियों के लिए fetchRequest बनाया गया है, और पिछले समाधान की तरह कोई मेमोरी कैश नहीं की गई थी। प्रॉपर्टी imagecache.relationship.image सही ढंग से दोषपूर्ण था। इस संपत्ति तक पहुंचने से गलती हुई और कैश भरने लगा। लेकिन इस मामले में, "imagecache" ऑब्जेक्ट ("पिता" ऑब्जेक्ट) पर [self.managedObjectContext refreshObject:object mergeChanges:NO]; कर रहा है, जिसके परिणामस्वरूप तुरंत कैश और मेमोरी को मुक्त कर दिया गया, फिर imagecache.relationship.image प्रॉपर्टी को गलती हुई। ध्यान दें: "बच्चे" ऑब्जेक्ट पर न करें, अगर आप [self.managedObjectContext refreshObject:object.relationship mergeChanges:NO] करते हैं, तो किसी कारण से कैश मुक्त नहीं होता है। मुझे लगता है कि यही कारण है कि आप रिश्ते को पार करते हैं।

3- मैंने कहा कि यह मुख्य रूप से एक अकादमिक प्रश्न था, इस मुद्दे के लिए वास्तविक "पूरे दिन" समाधान (बेहतर प्रदर्शन और कम सिरदर्द) कोर डेटा डेटाबेस के अंदर बड़े डेटा को बचाने से बचने के लिए है। आप अपने डेटा को फ़ाइलों के रूप में सहेज सकते हैं और केवल एक संदर्भ (फ़ाइलपैथ) स्टोर कर सकते हैं या आईओएस 5 के साथ आपके पास अपने कोर डेटा मॉडल के अंदर किसी भी "डेटा" प्रॉपर्टी पर "बाहरी स्टोरेज का उपयोग" सेट करने की संभावना है। यह आपके लिए सभी काम करेगा।

+1

अरे, मैं बस सोच रहा हूं कि क्या आपको कभी इस समस्या का कोई अन्य समाधान मिला है। दुर्भाग्यवश, मेरे पास कोई बड़ी NSData मेमोरी ऑब्जेक्ट्स नहीं है जो मैं समाधान 3 का उपयोग कर सकता हूं। इसके बजाय मेरे पास सैकड़ों हजार वस्तुएं हैं जो मानचित्र पर एनोटेशन के रूप में प्रदर्शित होती हैं। मैं बैचों में लाता हूं इसलिए मैं सुनिश्चित करता हूं कि यदि डिवाइस में पर्याप्त स्मृति नहीं है तो मैं सीमित कर सकता हूं कि डेटा कितना प्रदर्शित होता है। लेकिन जब मुझे स्मृति चेतावनी मिलती है और ताज़ा कॉल करें ऑब्जेक्ट: मर्ज चेंज: जैसा कि आपने उल्लेख किया है, स्मृति प्रभावित नहीं है, और मुझे स्मृति दुर्घटना हो रही है। कोई विचार? – horsejockey

0

मुझे लगता है कि आपको कम वस्तुओं को बैच में स्मृति में लोड करना चाहिए।

कोर्डाटा द्वारा जारी स्मृति दृश्यों के पीछे होती है और आपको इसके लिए प्रोग्राम नहीं करना पड़ता है; बुरी खबर यह है कि यह दृश्यों के पीछे होता है और इस प्रकार 'जादुई रूप से' स्मृति को चबा सकता है।

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

+0

हां, मैंने जो पहला समाधान लागू किया था वह केवल मुझे आवश्यक डेटा लाने के लिए था। यह मुख्य रूप से एक "अकादमिक" प्रश्न है। दस्तावेज इस बारे में स्पष्ट है, कैश प्रबंधन कोर डेटा द्वारा किया जाता है और सभी दृश्य के पीछे होते हैं, लेकिन यह भी कहता है कि कम स्मृति के मामले में, स्मृति मुक्त है। मुझे स्मृति चेतावनी के बाद कोर डेटा द्वारा उपयोग की जाने वाली स्मृति की कमी देखने की उम्मीद है। यह नहीं देख रहा, मैं सोच रहा था कि मेरे कोड में कुछ गड़बड़ है ...! मैं "मेरी आंखों के साथ" कोर डेटा को कम स्मृति स्थिति में स्मृति मुक्त करना चाहता हूं :-) – LombaX

+0

बस एक अपडेट: मैंने स्मृति (कुछ एनएसडीटा उदाहरण आवंटित करने वाला एक सरल लूप) पर कब्जा करने की कोशिश की, लेकिन कोर डेटा ने कभी भी स्मृति को मुक्त नहीं किया (मैंने कई बार कोशिश की, 100 एमबी एनएसडीटा आवंटित किया, फिर 200, फिर 300 ... जब तक ऐप दुर्घटनाग्रस्त हो गया)। ऐसा लगता है कि यह इसे मुक्त किए बिना fetchrequest के सभी डेटा कैश करता है, कभी नहीं! मुझे पता है कि मैं अपने दायरे तक पहुंचने के लिए अन्य दृष्टिकोणों का उपयोग कर सकता हूं, लेकिन यह अजीब लगता है। अगर वे राम का उपयोग जारी रखते हैं तो दोषपूर्ण गुणों का क्या अर्थ है? – LombaX

संबंधित मुद्दे