2012-01-12 9 views
40

जब लोग कहते हैं कि यह महंगा है तो लोगों का क्या अर्थ है? मैं केवल मध्यवर्ती भंडारण (एनएसएसटींग और एनएसडीएटी विशिष्ट हैं) के लिए बहुत से क्षणिक वस्तुओं के उदाहरण बनाते हैं। मुझे कैसे पता चलेगा कि मेरा प्रोग्राम NSDateFormatter का उपयोग कर रहा है या नहीं?NSDateFormatter आवंटित या प्रारंभ करने के लिए "महंगा" क्यों माना जाता है?

अब तक, मैंने सिंगलटन की मात्रा बनाने के लिए प्रतिबद्ध किया है, लेकिन मेरी वरीयता इसे अन्य कुछ वस्तुओं में शामिल करने के लिए होगी, जिससे मैं स्वयं संदर्भों का उपयोग कर सकूं।

प्रदर्शन प्रदर्शन परीक्षणों में से कम, मैं बेहतर "नियम-अंगूठे" समझ रहा हूं कि मुझे ऐसा क्यों करना चाहिए या नहीं करना चाहिए।

+0

रूपरेखा दर्दरहित – justin

+0

है आप निर्धारित करने के लिए जो तरीका अपनी आवश्यकताओं बेहतर सूट अपने अनुप्रयोग प्रोफ़ाइल कर सकते हैं। मुझे लगता है कि डेवलपर्स यह इंगित करना चाहते थे कि 'NSDateFormatter' के रूप में निर्दोष-ध्वनि के रूप में कुछ कुछ जटिल जटिल प्रारंभकर्ता कोड हो सकता है, इसलिए प्रारंभिक ऑब्जेक्ट को जितना संभव हो सके पुन: उपयोग करने के लिए दस्तावेज़ में एक संकेत दिया गया है। –

उत्तर

33

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    NSString *reuseIdentifier = @"cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; 

    MyManagedObject *managedObject = [self.managedObjects objectAtIndex:indexPath.row]; 
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 
    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 

    [cell.textLabel setText:[managedObject title]]; 
    [cell.detailTextLabel setText:[numberFormatter stringFromNumber:[managedObject amount]]]; 

    return cell; 
} 

इस कोड के स्क्रॉलिंग निष्पादन भयानक थी: मेरी पहली कोशिश निम्नलिखित था। फ्रेम दर लगभग 15 एफपीएस तक गिर गई क्योंकि मैं हर बार tableView:cellForRowAtIndexPath: पर एक नया NSNumberFormatter आवंटित कर रहा था।

मैं इस के लिए कोड को बदलने के द्वारा यह तय:

- (NSNumberFormatter *)numberFormatter { 

    if (_numberFormatter != nil) { 
     return _numberFormatter; 
    } 

    _numberFormatter = [[NSNumberFormatter alloc] init]; 
    [_numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 

    return _numberFormatter; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    NSString *reuseIdentifier = @"cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; 

    MyManagedObject *managedObject = [self.managedObjects objectAtIndex:indexPath.row]; 
    NSNumberFormatter *numberFormatter = [self numberFormatter]; 

    [cell.textLabel setText:[managedObject title]]; 
    [cell.detailTextLabel setText:[numberFormatter stringFromNumber:[managedObject amount]]]; 

    return cell; 
} 

यहाँ अंतर यह है कि मैं lazily एक इवर में NSNumberFormatter लोड कर दिया है, ताकि tableView:cellForRowAtIndexPath: के प्रत्येक रन नहीं रह गया है एक नया उदाहरण आवंटित करता है। इस सरल परिवर्तन ने स्क्रॉलिंग प्रदर्शन को लगभग 60 एफपीएस तक धक्का दिया।

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

+1

इसके साथ खतरा यह है कि आपको यह सुनिश्चित करना होगा कि आपका नंबरफॉर्मेटर को एक से अधिक धागे से नहीं कहा जाता है। यह concurrency का समर्थन नहीं करता है। –

+1

@GregMaletic यह एक बहुत ही सरल उदाहरण है, '' '' तालिका दृश्य: सेलफॉररोएट इंडेक्सपैथ: '' '' '' '' '' '' '' '' '' '' '' '' '' को कभी भी मुख्य धागे से नहीं बुलाया जाएगा। –

+0

@Eli True, लेकिन यदि आपका नंबर फ़ॉर्मेटर विधि को आपके कोड में किसी अन्य विधि में बुलाया जाता है, और उस विधि को किसी अन्य थ्रेड पर बुलाया गया था, तो आप स्वयं को पेंच कर सकते थे। आपको केवल मुख्य थ्रेड से अपना नंबरफॉर्मेटर विधि कॉल करना याद रखना होगा। –

7

मुझे कुछ समय पहले यही सवाल था। मैंने कुछ ऐप पर इंस्ट्रूमेंट्स चलाए हैं जो मैं काम कर रहा था और मुझे लगता है कि पिछले डेवलपर्स ने अपने द्वारा किए गए प्रत्येक कस्टम लॉग के लिए एक नया NSDateFormatter बनाया था। चूंकि प्रत्येक स्क्रीन के लिए वे लगभग 3 लाइनों को लॉग करते थे। ऐप केवल एक सेकेंड खर्च करने के लिए इस्तेमाल होता था जो केवल एनएसडीएटीफॉर्मेटर्स बनाते थे।

सरल समाधान आपके वर्ग में दिनांक स्वरूपक उदाहरण को एक विशेषता या कुछ के रूप में बनाए रखेगा और प्रत्येक लॉग लाइन के लिए इसका पुन: उपयोग करेगा।

कुछ मामूली सोच के बाद, मैं प्रारूप और लोकेल के आधार पर NSDateFormatters के पुन: उपयोग को संभालने के लिए "फैक्ट्री" के साथ आया हूं। मैं कुछ प्रारूप और लोकेल के डेट फॉर्मेटर का अनुरोध करता हूं और मेरी कक्षा पहले से लोड किए गए फॉर्मेटर को मुझे दे देती है। अच्छा प्रदर्शन ट्यूनिंग, आपको कोशिश करनी चाहिए।

पुनश्च: शायद किसी को यह परीक्षण करना चाहते हैं, तो मैं इसे सार्वजनिक नहीं किया: https://github.com/DougFischer/DFDateFormatterFactory/blob/master/README.md

+1

क्या आपको कोई प्रतिक्रिया मिली? – Dejell

+1

प्रतिक्रिया: एक आकर्षण की तरह काम करता है – Laszlo

+1

मैं सहमत हूं। आसान और सुविधाजनक। मेरे वर्तमान ऐप को इसका उपयोग करने से बहुत फायदा हुआ है। बहुत बहुत धन्यवाद – rmvz3

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