2013-08-23 7 views
10

मेरा आवेदन, मैंने जो प्रक्रिया लिखी है, वह स्मृति में बढ़ रही है और ऐसा नहीं लगता है।आईओएस [एआरसी] ऐप स्मृति जारी नहीं कर रहा है

पहली बात मैं उल्लेख करना चाहते हैं कि मैं क्या लिखा है की बुनियादी रूपरेखा इस है:
- एक यूआरएल (NSData -initWithContentsOfURL का उपयोग कर डेटा प्राप्त करने में) का अनुरोध करें
- NSDictionarys की NSArray में NSData पार्स NSJSONSerialization + JSONObjectWithStream
का उपयोग कर - लूप/डीकोड NSArray डालने/अद्यतन करने के माध्यम से डेटा के साथ FMDB ढांचे का उपयोग कर एक SQLite डेटाबेस में रिकॉर्ड को हटाने डीकोड

आवेदन ऊपर करता है, लेकिन यह एक अनिर्धारित अवधि के लिए एक पाश में यह करता है समय के साथ, जिसमें एप्लिकेशन "लोडिंग" एचयूडी प्रदर्शित करता है। मैंने सोचा कि यह उल्लेख करने लायक हो सकता है, हालांकि मुझे यह महत्वहीन लगता है कि यह इस प्रक्रिया को कितनी बार करता है, क्योंकि अगर यह ठीक से रिलीज़ हो रहा है तो स्मृति उपयोग को प्रभावित नहीं करना चाहिए। अगर मैं यहां गलत हूं, तो कृपया मुझे सलाह दें।

मेरा कोड ठीक काम करता है, ठीक है, यह करता है कि यह करने का इरादा है। हालांकि, जब मैं एप्लिकेशन कोड प्रोफाइल करता हूं, तो स्मृति केवल बढ़ती रहती है। यह पूरे हिस्सों में गिरावट करता है, लेकिन समग्र रूप से यह बढ़ता रहता है (आईई पहले जो भी इस्तेमाल किया गया था उसे पूरा नहीं करता है)।

जैसा कि मैंने पहले बताया था, आवंटन, लीक्स, वीएम ट्रैकर, और ट्रेस हाइलाइट्स के साथ एप्लिकेशन का प्रोफाइल किया है।

ट्रेस हाइलाइट्स: शो है कि स्मृति के उपयोग धीरे-धीरे ऊपर जा रहा है, लेकिन कुछ स्मृति (सभी नहीं) जिसका अर्थ है यदि प्रक्रिया काफी लंबे समय स्मृति के लिए चल रहा है उच्च उपयोग तक पहुँचने और उन्हें समाप्त कर देंगे छोड़ने।

आवंटन: ठीक लगता है। आवंटन में स्पाइक्स होते हैं लेकिन यह हमेशा शुरू होता है जहां यह शुरू हुआ। मैं heapshots लिया और वे हमेशा खंड प्रति अधिकतम 500-700kb (लगभग 10 मिनट के लिए छोड़ दिया)

वीएम ट्रैकर छोड़ने ड्रॉप डाउन: कि स्मृति लगातार बढ़ जाता है दिखाने के लिए साबित होता है, और पूर्ण स्मृति को रिहा नहीं किया गया है (के रूप में पता लगाने में खोज की पर प्रकाश डाला)। निवासी वास्तव में उच्च पाने के लिए लगता है

लीक: नहीं लीक आवेदन में पाया

यहाँ आवंटन/VM ट्रैकर चल के कुछ स्क्रीनशॉट है:
enter image description here enter image description here

यह ध्यान देने योग्य मैं वास्तव में है कि लायक है कोशिश की:
- ऑटोरेलीजपूल
- प्रत्येक गुण को निर्दिष्ट करके "बल जारी करना" जोड़ना; जैसे कि NSURLs, NSRequests, आदि; शून्य

मेरे सवालों का:
- मैं कुछ स्मृति जारी करने के लिए विशेष कर किया जाना चाहिए?
- मैं इस मुद्दे को और कैसे डीबग कर सकता हूं?
- डेटा से क्या गलत है मुझे पता चल सकता है कि उपकरण मुझे क्या देता है?

---- संपादित करें: ----
यहाँ कोड है कि डेटा प्राप्त करने का यूआरएल अनुरोध भेजता है।:

- (void) requestAndParse : (NSString *)url 
{ 
    NSURL *theURL; 
    ASIHTTPRequest *request; 
    NSData *collectedData; 
    NSError *error; 
    @try { 
        // File cache the NSData 
        theURL = [[NSURL alloc] initWithString: url]; 
        request = [ASIHTTPRequest requestWithURL: theURL]; 
        [request setDownloadDestinationPath: [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]]; 
        [request startSynchronous]; 
        [request waitUntilFinished]; 

        collectedData = [[NSData alloc] initWithContentsOfFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]]; 


        if ([collectedData length] > 0) { 
         records = [NSJSONSerialization JSONObjectWithData:collectedData options:NSJSONReadingMutableContainers error:&error]; 
        } 

    } 
    @catch (NSException *exception) { 

        // Failed 
        NSLog(@"Parse error: %@", error); 

    } 
    @finally { 

        // DB updates with the records here 
        ... 

        // remove file 
        [[NSFileManager defaultManager] removeItemAtPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"] error:nil]; 
        // release properties used 
        collectedData = nil; 
        request = nil; 
        theURL = nil; 
    } 

} 

यह उपरोक्त विधि एप्लिकेशन प्रतिनिधि में थोड़ी देर के भीतर से बुलाया जाता है। जबकि लूप एक अनिश्चित लंबाई है, जैसा कि पहले उल्लेख किया गया था।

--- संपादित करें 2: ---

निम्नलिखित क्या @finally बयान (FMDB का उपयोग कर SQLite डेटाबेस अद्यतन) के भीतर होता है। मेरी कक्षा में इनमें से कई विधियां हैं, प्रत्येक तालिका के लिए एक। वे सभी एक ही पैटर्न का पालन हालांकि, के रूप में वे सभी पहले एक से दोहराया गया है:

-(BOOL) insertBatchOfRecords:(NSArray *)records { 

__block BOOL queueReturned = YES; 

@autoreleasepool { 

    FMDatabaseQueue *dbQueue = [self instantiateDatabaseQueue]; 
    [dbQueue inTransaction:^(FMDatabase *tdb, BOOL *rollback) { 
     if (![tdb open]) { 
      NSLog(@"Couldn't open DB inside Transaction"); 
      queueReturned = NO; 
      *rollback = YES; 
      return; 
     } 

     for (NSDictionary *record in records) { 
      [tdb executeUpdate:@"INSERT OR REPLACE INTO table (attr1, attr2) VALUES (?,?)", [record valueForKey:@"attr1"], [record valueForKey:@"attr2"]]; 

      if ([tdb hadError]) { 
       queueReturned = NO; 
       *rollback = YES; 
       NSLog(@"Failed to insert records because %@", [tdb lastErrorMessage]); 
       return; 
      } 
     } 
    }]; 

    [dbQueue close]; 
    dbQueue = nil; 

} 

return queueReturned; 
} 

और इस प्रकार -instantiateDatabaseQueue विधि है:

-(FMDatabaseQueue *) instantiateDatabaseQueue { 
@autoreleasepool { 
    return [FMDatabaseQueue databaseQueueWithPath: [self.getDocumentsDirectory stringByAppendingPathComponent:@"localdb.db"]]; 
} 
} 

autoreleasepools यह गन्दा कर सकता है, लेकिन कोड मूल रूप से ये नहीं था। मैंने उन्हें विभिन्न स्थानों पर लागू किया ताकि यह देखने के लिए कि कोई सुधार हुआ था (वहां नहीं था)।

--- संपादित 3 ---

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

मैंने और अधिक प्रोफाइलिंग तस्वीरें ली हैं, और अभी भी मुश्किल समय की पहचान करने में कठिनाई हो रही है। नीचे देखें कि आवंटन ठीक दिखता है (वीएम भी मुझे बहुत बुरा नहीं लग रहा है?), और अभी भी कोई लीक नहीं है (इसकी कोई तस्वीर नहीं है, क्योंकि कोई नहीं है !!)

हालांकि, जब मैंने ट्रेस पर प्रोफाइल किया हाइलाइट्स, स्मृति उपयोग केवल बहुत अधिक उपयोग तक पहुंचने तक, 3 जीएस पर लगभग 70 + एमबी तक पहुंचने तक और फिर बहुत मेमोरी का उपयोग करने के कारण दुर्घटनाग्रस्त हो जाता है।

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

मैं (बजाय फाइल करने के लिए भंडार) NSData हथियाने के लिए ASIHTTPRequest का उपयोग करके समस्या कम कर दिया। कृपया ऊपर संशोधित कोड देखें। हालांकि, समस्या अभी भी बनी हुई है, बस होने में लंबा समय लगता है!

, मूल रूप से प्रति सवाल के रूप में:
- वहाँ कुछ इस एप्लिकेशन प्रक्रिया के दूसरे भाग के साथ कुछ गलत है?

+1

+1 अच्छा पहला सवाल है। हालांकि, कुछ कोड शामिल करने की आवश्यकता हो सकती है। –

+2

क्या आपने यह देखने के लिए स्टैकशॉट का उपयोग किया है कि वास्तव में नए आवंटन क्या हैं? क्या आप रनलोप को चलाने का मौका दे रहे हैं? (छोटे ऑपरेशन में अपने लंबे लूप को तोड़ने और एनएसओपरेशन क्यूयू के साथ प्रसंस्करण पर विचार करें)। – bneely

+0

मैंने उस वास्तविक कोड को शामिल किया है जो यूआरएल अनुरोध भेजता है और उसे सरणी में तोड़ देता है। – Joshua

उत्तर

1

एआरसी के साथ आईओएस में कोशिश/पकड़ का उपयोग स्मृति स्मृति रिसाव का कारण बन सकता है, और सबसे अच्छा बचा है।

एक वैकल्पिक दृष्टिकोण एक async NSURLConnection, या एक synch NSURLConnection के साथ एक NSOperation का उपयोग करना है।

+0

बहुत सच है। यह दुखद लेकिन सच है। – Sulthan

+0

इस उदाहरण में उपयोग की जाने वाली कोशिश/पकड़ रिसाव का कारण नहीं बन रही है, जिसे मैं निश्चित करता हूं क्योंकि इस समस्या को ध्यान में रखते हुए प्रयास पकड़ लागू किया गया था। Async NSURLConnection का भी उपयोग किया गया था लेकिन इसे सिंक्रोनस में बदल दिया गया था क्योंकि मुख्य थ्रेड को अवरुद्ध किया जा रहा था जब तक कि एसिंक समाप्त नहीं हुआ। एनईएक्सटी कदम एनएसओपरेशन उपयोग की जांच करना है जो मैं आज करूँगा और परिणामों के साथ वापस पोस्ट करूंगा। – Joshua

+0

उस मामले में क्या आप सुनिश्चित हैं कि अनुरोध एंडपर्स विधि लीक का कारण बन रही है? – Ronan

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