2009-12-21 22 views
10

मेरे आवेदन में मैं एनएसओपरेशनक्यूयू के भीतर एनएसआईएनवोकेशनऑपरेशंस के रूप में 10 एसिंक्रोनस NSURLConnections निष्पादित कर रहा हूं। के रूप में यहाँ देखा आदेश कनेक्शन से पहले लौटने से प्रत्येक ऑपरेशन को रोकने के लिए मैं CFRunLoopRun() फोन खत्म करने के लिए का अवसर मिल सके:आईफोन 3 जीएस पर 100% सीपीयू का उपभोग करने वाले पृष्ठभूमि धागे गुप्त मुख्य धागे

- (void)connectInBackground:(NSURLRequest*)URLRequest { 
TTURLConnection* connection = [[TTURLConnection alloc] initWithRequest:URLRequest delegate:self]; 

// Prevent the thread from exiting while the asynchronous connection completes the work. Delegate methods will 
// continue the run loop when the connection is finished. 
CFRunLoopRun(); 

[connection release]; 
} 
कनेक्शन खत्म

, अंतिम कनेक्शन प्रतिनिधि चयनकर्ता कॉल CFRunLoopStop (CFRunLoopGetCurrent()) , (connectInBackground में निष्पादन) को फिर से शुरू यह आम तौर पर वापस लौटने का मौका:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    TTURLConnection* ttConnection = (TTURLConnection*)connection; 
    ... 
    // Resume execution where CFRunLoopRun() was called. 
    CFRunLoopStop(CFRunLoopGetCurrent()); 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    TTURLConnection* ttConnection = (TTURLConnection*)connection; 
    ... 
    // Resume execution where CFRunLoopRun() was called. 
CFRunLoopStop(CFRunLoopGetCurrent()); 
} 

यह अच्छी तरह से काम करता है और यह सुरक्षित थ्रेड क्योंकि मैं प्रत्येक कनेक्शन की प्रतिक्रिया और TTURLConnection उपवर्ग में उदाहरण चर के रूप में डेटा बंडल है।

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

इस समस्या के साथ समस्या यह है कि इन धागे (स्प्रिंगबोर्ड और डीटीमोबाइलिस की सहायता से) सभी उपलब्ध CPU समय का उपभोग करते हैं और मुख्य धागा को गुप्त बनने का कारण बनता है। दूसरे शब्दों में, एक बार जब सीपीयू 100% उपयोग किया जाता है, तो मुख्य थ्रेड यूआई घटनाओं को प्रोसेस नहीं कर रहा है जितना तेज़ यूआई बनाए रखने के लिए इसकी आवश्यकता होती है। विशेष रूप से, तालिका दृश्य स्क्रॉलिंग झटकेदार हो जाता है।

Process Name % CPU 
SpringBoard 45.1 
MyApp   33.8 
DTMobileIS 12.2 
... 

उपयोगकर्ता स्क्रीन के साथ सूचना का आदान प्रदान या तालिका मुख्य थ्रेड की प्राथमिकता स्क्रॉल है, वहीं हो जाता है 1.0 (उच्चतम संभव) और उसके रन पाश मोड UIEventTrackingMode हो जाता है। प्रत्येक ऑपरेशन के धागे डिफ़ॉल्ट रूप से 0.5 प्राथमिकता और NSDefaultRunLoopMode में एसिंक्रोनस कनेक्शन चलते हैं। प्राथमिकताओं और मोड के आधार पर धागे और उनके रन लूप कैसे इंटरैक्ट करते हैं, इस बारे में मेरी सीमित समझ के कारण, मैं स्टंप हो गया हूं।

क्या मेरे ऐप के बैकग्राउंड थ्रेड में सभी उपलब्ध CPU समय सुरक्षित रूप से उपभोग करने का कोई तरीका है, जबकि अभी भी गारंटी है कि इसका मुख्य थ्रेड जितना आवश्यक हो उतना सीपीयू दिया जाता है? शायद मुख्य थ्रेड को जितनी बार इसे चलाने की आवश्यकता होती है उसे चलाने के लिए मजबूर कर सकते हैं? (मैंने सोचा था कि धागा प्राथमिकताओं कि का ध्यान रखा गया होगा।)

अद्यतन 12/23: मैं अंत में सीपीयू नमूना पर एक संभाल दिखने लगी और वजहों यूआई चिड़चिड़ा होता जा रहा था के सबसे मिल गया है। सबसे पहले, मेरा सॉफ़्टवेयर एक लाइब्रेरी को कॉल कर रहा था जिसमें परस्पर बहिष्करण सेमफोर थे। ये ताले समय के लिए मुख्य धागे को अवरुद्ध कर रहे थे जिससे स्क्रॉल थोड़ा छोड़ने लगा।

इसके अतिरिक्त, मुझे कुछ महंगा NSFileManager कॉल और एमडी 5 हैशिंग फ़ंक्शन मिले जो चलाने के लिए बहुत अधिक समय ले रहे थे। बड़ी वस्तुओं को आवंटित करने से अक्सर मुख्य धागे में कुछ अन्य प्रदर्शन हिट होते हैं।

मैंने इन मुद्दों को हल करना शुरू कर दिया है और प्रदर्शन पहले से कहीं अधिक बेहतर है। मेरे पास 5 एक साथ कनेक्शन हैं और स्क्रॉलिंग चिकनी है, लेकिन मेरे पास अभी भी और काम है। मैं मुख्य थ्रेड के प्रदर्शन को प्रभावित करने वाले मुद्दों का पता लगाने और ठीक करने के लिए सीपीयू नमूने का उपयोग करने के तरीके पर एक गाइड लिखने की योजना बना रहा हूं। टिप्पणियों के लिए धन्यवाद अब तक, वे सहायक थे!

अद्यतन 2010/01/14: स्वीकार्य प्रदर्शन को प्राप्त करने के बाद मुझे एहसास है कि CFNetwork ढांचा कभी कभी स्मृति लीक किया गया था शुरू कर दिया।अपवादों को यादृच्छिक रूप से (हालांकि, शायद ही कभी) सीएफनेटवर्क के अंदर उठाया जा रहा था! मैंने उन समस्याओं से बचने के लिए जो भी कर सकता था, मैंने कोशिश की लेकिन कुछ भी काम नहीं किया। मुझे पूरा यकीन है कि मुद्दे NSURLConnection के भीतर दोषों के कारण हैं। मैंने परीक्षण कार्यक्रम लिखे जो अभ्यास NSRLConnection को छोड़कर कुछ भी नहीं किया और वे अभी भी दुर्घटनाग्रस्त हो रहे थे और लीक कर रहे थे।

आखिरकार मैंने ASIHTTPRequest के साथ NSURLConnection को बदल दिया और क्रैशिंग पूरी तरह से बंद हो गई। सीएफनेटवर्क लगभग कभी लीक नहीं होता है, हालांकि, अभी भी एक बहुत दुर्लभ रिसाव है जो DNS नाम को हल करते समय होता है। मैं अब काफी संतुष्ट हूँ। उम्मीद है कि यह जानकारी आपको कुछ समय बचाती है!

+0

मैं उन थ्रेडों के खिलाफ अनुशंसा करता हूं जो किसी भी फोन पर 100% CPU का उपभोग करते हैं। आप बैटरी को तेजी से निकाल देंगे। –

+0

यदि उपयोगकर्ता अधिक सामग्री चाहता है, तो वे इसे पाने के लिए स्क्रॉल करते हैं। सीपीयू का उपयोग तब किया जाता है जब उपयोगकर्ता इसका अनुरोध करता है। कोको के थ्रेडिंग मॉडल को ऐसा करने में कोई समस्या नहीं होनी चाहिए। UI थ्रेड को ट्रैक करते समय मुख्य थ्रेड 1.0 प्राथमिकता के साथ चलता है और मेरे पृष्ठभूमि धागे केवल 0.5 होते हैं। मैं मुख्य धागे के लिए गारंटीकृत CPU समय आवंटित करना चाहता हूं। क्या यह संभव है? –

उत्तर

7

प्रैक्टिस में आप बस दो या तीन से अधिक पृष्ठभूमि नेटवर्क धागे नहीं रख सकते हैं और यूआई पूरी तरह उत्तरदायी रहेगा।

उपयोगकर्ता प्रतिक्रिया के लिए अनुकूलित करें, यह एकमात्र चीज है जिसे उपयोगकर्ता वास्तव में नोटिस करता है। या (और मैं वास्तव में यह कहने से नफरत करता हूं) अपने ऐप में एक "टर्बो" बटन जोड़ें जो एक गैर-इंटरैक्टिव मोडल डायलॉग रखता है और यह चालू होने पर 10 तक समवर्ती संचालन को बढ़ाता है।

+1

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

3

ऐसा लगता है कि NSOperationQueueDefaultMaxConcurrentOperationCount किसी कारण से 1 पर सेट है! मुझे लगता है कि आप अपने खराब फोन को ओवरलोड कर रहे हैं। आप थ्रेडिंग प्राथमिकताओं के साथ गड़बड़ कर सकते हैं - मुझे लगता है कि मैक कोर उपलब्ध है और आधिकारिक रूप से धन्य एपीआई का हिस्सा है - लेकिन मेरे लिए यह गलत दृष्टिकोण की तरह लगता है।

"सिस्टम" स्थिरांक का उपयोग करने के फायदों में से एक यह है कि ऐप्पल आपके लिए ऐप को ट्यून कर सकता है। मूल आईफोन पर चलाने के लिए आप इसे कैसे ट्यून करने जा रहे हैं? अगले साल क्वाड कोर आईफोन के लिए 10 उच्च पर्याप्त है?

+0

मैं वास्तव में डिवाइस के बजाए उपयोगकर्ता के लिए डिज़ाइन को अनुकूलित कर रहा हूं। हमारे दिमाग हर 2 साल में क्षमता में दोगुना नहीं करते हैं या करते हैं?)। यहां तक ​​कि यदि मशीन एक ही समय में 1000 वस्तुओं को लाने में सक्षम है, तो मैं नहीं चाहूंगा। यदि मैं उपयोगकर्ता पर गलत मात्रा में सामग्री फेंकता हूं तो वे या तो अभिभूत हो जाएंगे, या बदतर, ऊब जाएंगे। –

+1

यदि आप इतने सारे CPU का उपभोग कर रहे हैं तो मुख्य (UI) थ्रेड भूखा हो जाता है - तो आप उपयोगकर्ता के लिए अनुकूलन नहीं कर रहे हैं, आप नेटवर्क थ्रूपुट के लिए अनुकूलित कर रहे हैं। वे दो बहुत ही अलग चीजें हैं। उपयोगकर्ता के लिए अनुकूलन का अर्थ उपलब्ध संसाधनों को संतुलित करना है, लेकिन अक्सर इसका मतलब है "यूआई उत्तरदायी रखें"। यह सब से ऊपर प्राथमिक नियम है, जब तक यूआई अभी भी उत्तरदायी है, तब तक उपयोगकर्ता कुछ और सेकंड तक बैठ सकता है। –

+0

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

0

जेम्स, हालांकि मुझे आपकी समस्या का अनुभव नहीं हुआ है, मैंने जो सफलता प्राप्त की है, वह NSOperation उपclass के भीतर डाउनलोड करने के लिए सिंक्रोनस कनेक्शन का उपयोग कर रहा है।

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

मैं नेटवर्क स्थानों से चित्र संपत्ति हथियाने और लक्ष्य को अद्यतन करने UIImageView रों के लिए इस दृष्टिकोण का उपयोग। डाउनलोड NSOperationQueue में होता है और छवि-दृश्य को अद्यतन करने वाली विधि मुख्य थ्रेड पर होती है।

+0

मैंने वास्तव में सिंक्रोनस अनुरोधों का उपयोग करने का प्रयास किया है लेकिन ऐसा लगता है कि ऐसा ही प्रतीत होता है। यह समझ में आता है क्योंकि ऐप्पल के प्रलेखन का कहना है कि सिंक्रोनस कनेक्शन एसिंक्रोनस कनेक्शन के शीर्ष पर बनाया गया है। –

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