2011-02-07 4 views
14

में HTTP पर छवियों को लाने के दौरान लगातार स्मृति आवंटन बढ़ रहा है, मैं एक आईओएस ऐप लागू कर रहा हूं जिसे HTTP पर बड़ी मात्रा में छवियां लाने की आवश्यकता है। मैंने कई दृष्टिकोणों की कोशिश की है लेकिन स्वतंत्र रूप से मैं क्या करता हूं, स्मारक लगातार स्मृति आवंटन में वृद्धि दिखाता है और जब मैं इसे किसी डिवाइस पर चलाता हूं तो ऐप क्रैश हो जाता है। उपकरण द्वारा दिखाए गए कोई रिसाव नहीं हैं।आईओएस

अब तक मैं कोशिश की है निम्नलिखित approches:

  • एक NSOperation
  • भीतर एक तुल्यकालिक NSURLConnection का उपयोग कर छवियां प्राप्त एक NSOperation
  • के भीतर एक अतुल्यकालिक NSURLConnection का उपयोग कर छवियों में लाएं का उपयोग छवियों में प्राप्त करें [ NSData डेटा WithContentsOfURL: url] मुख्य-थ्रेड
  • एनएसओपरेशन
  • में सिंक्रोनस ASIHTTPRequest का उपयोग करके छवियां प्राप्त करें अतुल्यकालिक ASIHTTPRequest का उपयोग कर और एक NSOperationQueue
  • में जोड़ने छवियों अतुल्यकालिक ASIHTTPRequest का उपयोग कर और एक completionBlock

instrumetns में कॉल ट्री पता चलता है कि स्मृति सेवन किया जाता है HTTP-प्रतिक्रिया को संसाधित करते समय का उपयोग कर छवियां प्राप्त करें। अतुल्यकालिक NSURLConnection के मामले में यह

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
[receivedData appendData:data]; 
} 

तुल्यकालिक NSURLConnection के मामले में में, उपकरण एक बढ़ती CFData (स्टोर) प्रविष्टि से पता चलता है। ASIHTTPRequest के साथ समस्या एक समान कोड-स्थिति में एसिंक्रोनस NSURLConnection के समान ही प्रतीत होती है। [NSData डेटा WithContentsOfURL: url] दृष्टिकोण सटीक रूप से उस कथन में कुल स्मृति आवंटन की बढ़ती मात्रा दिखाता है।

जब मैं एक अलग थ्रेड में अनुरोध किया जाता है तो मैं एक NSAutoReleasePool का उपयोग कर रहा हूं और मैंने [[NSURLCache sharedURLCache] removeAllCachedResponses को हटाएं] - कोई सफलता नहीं है।

समस्या को हल करने के लिए कोई विचार/संकेत? धन्यवाद।

संपादित करें: व्यवहार केवल तब दिखाता है जब मैं CoreData का उपयोग कर छवियों को जारी रखता हूं।

-(void) _fetchAndSave:(NSString*) imageId { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
NSString *url = [NSString stringWithFormat:@"%@%@", kImageUrl, imageId]; 
HTTPResponse *response = [SimpleHTTPClient GET:url headerOrNil:nil]; 
NSData *data = [response payload]; 

if(data && [data length] > 0) { 
    UIImage *thumbnailImage = [UIImage imageWithData:data]; 
    NSData *thumbnailData = UIImageJPEGRepresentation([thumbnailImage scaleToSize:CGSizeMake(55, 53)], 0.5); // UIImagePNGRepresentation(thumbnail); 

    [self performSelectorOnMainThread:@selector(_save:) withObject:[NSArray arrayWithObjects:imageId, data, thumbnailData, nil] waitUntilDone:NO]; 
} 
[pool release]; 
} 

सभी CoreData संबंधित सामग्री यहां मुख्य-थ्रेड में किया जाता है, इसलिए वहाँ किसी भी CoreData बहु सूत्रण मुद्दा नहीं होना चाहिए: यहाँ कोड मैं एक NSInvocationOperation के रूप में चलाया जाता है। हालांकि, अगर मैं छवियों को जारी रखता हूं, तो उपकरण ऊपर वर्णित पदों पर निरंतर स्मृति आवंटन को दिखाता है।

द्वितीय संपादित करें:

CoreData संबंधित कोड:

-(void) _save:(NSArray*)args { 
NSString *imageId = [args objectAtIndex:0]; 
NSData *data = [args objectAtIndex:1]; 
NSData *thumbnailData = [args objectAtIndex:2]; 

Image *image = (Image*)[[CoreDataHelper sharedSingleton] createObject:@Image]; 
image.timestamp = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; 
image.data = data; 

Thumbnail *thumbnail = (Thumbnail*)[[CoreDataHelper sharedSingleton] createObject:@"Thumbnail"]; 
thumbnail.data = thumbnailData; 
thumbnail.timestamp = image.timestamp; 
[[CoreDataHelper sharedSingleton] save]; 
} 

CoreDataHelper (self.managedObjectContext NSManagedObjectContext वर्तमान सूत्र में प्रयोग करने योग्य उठा रहा है) से:

-(NSManagedObject *) createObject:(NSString *) entityName { 
return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext]; 
} 
+0

क्या आप समस्या को [छोटे कोड नमूना] (http://sscce.org/) के साथ पुन: पेश कर सकते हैं और पोस्ट कर सकते हैं? – zoul

+0

मैं नहीं कर सका! Altough Instruments उल्लिखित स्थानों में स्मृति को बढ़ाना दिखाता है, व्यवहार केवल तब दिखाता है जब मैं CoreData का उपयोग कर छवियों को कैश करता हूं। – sink12

+0

क्या आपको स्मृति की निरंतर वृद्धि का कारण मिला? –

उत्तर

0

इस में मामला, आप वास्तव में देख रहे हैं कि आप क्या देखना चाहते हैं। -[NSMutableData appendData:] नए डेटा को पकड़ने के लिए अपने आंतरिक बफर के आकार को बढ़ाता है।चूंकि NSMutableData हमेशा स्मृति में स्थित है, इसलिए यह स्मृति उपयोग में समान वृद्धि का कारण बनता है। आप क्या उम्मीद कर रहे थे

यदि इन छवियों के लिए अंतिम गंतव्य डिस्क पर है, तो NSMutableData के बजाय NSOutputStream का उपयोग करने का प्रयास करें। यदि आप छवि को प्रदर्शित करना चाहते हैं, तो आप फ़ाइल को इंगित करते समय UIImage बना सकते हैं।

+0

एनएसएमयूटेबलडेटा ऑब्जेक्ट जारी करने के बाद भी, स्मृति को मुक्त नहीं किया जा रहा है। – sink12

+0

कोई और व्यक्ति 'एनएसएमयूटेबलडेटा' उदाहरण का संदर्भ रख सकता है। मैं आपके द्वारा पोस्ट किए गए कोड से नहीं बता सकता हूं। साथ ही, इस बात की कोई गारंटी नहीं है कि ओएस वास्तव में स्मृति के रूप में आपके द्वारा किए जाने के साथ ही मुक्त हो जाएगा। कई मामलों में, यह आवंटित किया जाएगा ताकि इसका उपयोग फिर से किया जा सके ('malloc()' 'sbrk() 'को कॉल करने के बजाय' धीमा हो सकता है।) –

9

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

समस्या NSRLCache समस्या थी। आपने कहा है कि आपने [[NSURLCache sharedURLCache] निकालें सभी कैश किए गए रीस्पॉन्स]। हमने भी कोशिश की, लेकिन फिर कुछ अलग कोशिश की।

हमारी डाउनलोड एन छवियों/सिनेमा, जहां एन था आम तौर पर 50 500 करने के लिए यह महत्वपूर्ण है कि हम एक परमाणु आपरेशन के रूप में एन के सभी मिलता था के समूह में किया जाता है।

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:0]; 
[NSURLCache setSharedURLCache:sharedCache]; 

हम तो एक तुल्यकालिक कॉल के साथ एन HTTP पर में प्रत्येक छवि मिलती है:

इससे पहले कि हम http डाउनलोड के हमारे समूह शुरू कर दिया है, हम ऐसा किया। हम एनएसओपरेशन में इस समूह को डाउनलोड करते हैं, इसलिए हम यूआई को अवरुद्ध नहीं कर रहे हैं।

NSData *movieReferenceData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

अंत में, प्रत्येक व्यक्ति छवि डाउनलोड करने के बाद, और उसके बाद हम उस छवि के लिए हमारे NSData वस्तु के साथ काम हो गया है, हम कहते हैं:

[sharedCache removeAllCachedResponses]; 

हमारी स्मृति आवंटन शिखर व्यवहार एक बहुत ही आराम से मुट्ठी को गिरा दिया मेगाबाइट्स, और बढ़ने बंद कर दिया।

+0

मैंने वही किया लेकिन मेरा cfdata (store) रहता है बढ़ रही है। मैं इसे बीजी थ्रेड बीटीडब्ल्यू में कर रहा हूं (यदि यह कोई अंतर बनाता है) –

+0

क्या आप बाइट्स कॉपी कर रहे हैं या CFDataCreateWithBytesNoCopy का उपयोग कर रहे हैं? शायद आप एक प्रतिलिपि पर लटक रहे हैं जिसकी आप उम्मीद नहीं करते थे। (https://developer.apple.com/library/mac/#documentation/CoreFOundation/Conceptual/CFBinaryData/Tasks/CFWorkingBinaryData.html#//apple_ref/doc/uid/20002120-CJBDBHCB) –

+0

नहीं ..... बीमार कोशिश करें और देखें कि क्या होता है –