2012-01-24 14 views
5

2 विकल्प हैं (संभवतः अधिक)। NSSet एक उदाहरण के रूप का उपयोग करना:एक गैर-परिवर्तनीय वस्तु की एक परिवर्तनीय प्रति बनाने के लिए पसंदीदा तरीका?

NSMutableSet * mutableSet = [ NSMutableSet setWithSet:nonMutableSet ] ; 

या

NSMutableSet * mutableSet = [ [ nonMutableSet mutableCopy ] autorelease ] ; 

कि इन दो कार्यान्वयन के बीच कोई अंतर है? क्या एक "अधिक कुशल" है? (अन्य उदाहरण NSArray/NSMutableArray और NSDictionary/NSMutableDictionary

+0

अच्छा सवाल है, और मुझे संदेह है कि इस पर बहुत बहस हो सकती है। –

+0

यदि आप सभी को एक पक्ष करना चाहते हैं, तो इसे बेंचमार्क करें और खुद को प्रश्न का उत्तर दें :) मुझे संदेह है कि इसमें कोई अंतर नहीं होना चाहिए। – fzwo

+0

@fzwo मुझे लगता है कि मैं ऐसा कर सकता हूं .. हालांकि यह आंशिक रूप से एक प्रोग्रामिंग दर्शन प्रश्न है :) – nielsbot

उत्तर

7

बेंचमार्क मजेदार होगा :)

#import <Foundation/Foundation.h> 

int main (int argc, const char * argv[]) 
{ @autoreleasepool { 
    NSMutableSet *masterSet = [NSMutableSet set]; 

    for (NSInteger i = 0; i < 100000; i++) { 
     [masterSet addObject:[NSNumber numberWithInteger:i]]; 
    } 

    clock_t start = clock(); 

    for (NSInteger i = 0; i < 100; i++) { 
     @autoreleasepool { 
      [NSMutableSet setWithSet:masterSet]; 
     } 
    } 

    NSLog(@"a: --- %lu", clock() - start); 

    sleep(1); 

    start = clock(); 

    for (NSInteger i = 0; i < 100; i++) { 
     @autoreleasepool { 
      [[masterSet mutableCopy] autorelease]; 
     } 
    } 

    NSLog(@"b: --- %lu", clock() - start); 

    return 0; 
} } 

मेरी मशीन पर (10.7), setWithSet: है ~ 3x -mutableCopy की तुलना में धीमी (किसी की कोशिश करना चाहते है आईओएस 5 पर? :))

अब सवाल यह है: क्यों?

-mutableCopy अपने अधिकांश समय CFBasicHashCreateCopy() में खर्च कर रहा है (CFBasicHash.m देखें)। ऐसा लगता है कि बिना किसी रीहैशिंग के सीधे हैश बाल्टी की प्रतिलिपि बना रही है।

Running Time Self Symbol Name 
256.0ms 61.5% 0.0 -[NSObject mutableCopy] 
256.0ms 61.5% 0.0  -[__NSCFSet mutableCopyWithZone:] 
256.0ms 61.5% 0.0  CFSetCreateMutableCopy 
255.0ms 61.2% 156.0  CFBasicHashCreateCopy 
97.0ms 23.3% 44.0   __CFSetStandardRetainValue 

-setWithSet सेट के प्रत्येक मान के माध्यम से गणना कर रहा है, और फिर इसे नए सेट में जोड़ रहा है। CFBasicHashAddValue के कार्यान्वयन से (फिर से CFBasicHash.m में), ऐसा लगता है कि यह सेट में प्रत्येक मान को रीहाश कर रहा है।

Running Time Self Symbol Name 
1605.0ms 86.0% 0.0  +[NSSet setWithSet:] 
1605.0ms 86.0% 2.0  -[NSSet initWithSet:copyItems:] 
1232.0ms 66.0% 68.0  -[__NSPlaceholderSet initWithObjects:count:] 
1080.0ms 57.8% 299.0   CFBasicHashAddValue 
324.0ms 17.3% 28.0  -[NSSet getObjects:count:] 
272.0ms 14.5% 75.0   __CFBasicHashFastEnumeration 

यह रिहाश सीएफएससेट स्तर पर समझ में आता है। CFSets कॉलबैक पैरामीटर में एक CFSetHashCallBack लेते हैं; इस प्रकार, CFNumbers के दो सीएफएससेट्स में एक अलग हैशिंग रूटीन निर्दिष्ट हो सकता है। फाउंडेशन का एनएसएससेट सीएफएससेट अंडर-द-हूड का उपयोग करता है, और इसमें एक सीएफएसएट हैशकॉलबैक फ़ंक्शन है जो -[NSObject hash] को आमंत्रित करता है। (हालांकि मुझे लगता है कि ऐप्पल इस मामले को अनुकूलित कर सकता है और दो सेटों के समान हैश कॉलबैक होने पर रिहाश से बच सकता है)।

ध्यान दें कि यह बेंचमार्क केवल एनएसएससेट (एनएसएनबर्स के) के लिए है, अन्य संग्रह वर्गों में विभिन्न प्रदर्शन विशेषताओं हो सकती हैं।

+0

मेरा मानना ​​है कि Arrays के पास वस्तुओं की संख्या जैसे परिस्थितियों के आधार पर विभिन्न बैकिंग कार्यान्वयन (एनएसएआरएआरई क्लास क्लस्टर के निजी उप-वर्गों में) हो सकते हैं, जो आगे बेंचमार्किंग जटिल करता है (लेकिन आम तौर पर प्रदर्शन में सुधार करता है)। – fzwo

+1

हाँ! साथ ही, संग्रह में वस्तुओं की संख्या भी एक अंतर बना सकती है। उपरोक्त बेंचमार्क का उपयोग करते हुए सरणी के लिए, ऐसा लगता है कि -mutableCopy/-autorelease थोड़ा धीमा है * इन चीजों को अक्सर ट्यून किया जाता है - फाउंडेशन की प्रदर्शन विशेषताओं के बारे में धारणा बनाने के बजाय कभी-कभी बेंचमार्क को फिर से शुरू करना एक अच्छा विचार है कक्षाएं :) – iccir

+0

मेरे लिए उत्तर के रूप में गिना जाता है! धन्यवाद। – nielsbot

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