2012-01-24 30 views
5

Có 2 lựa chọn (có thể nhiều hơn). Sử dụng NSSet làm ví dụ:Cách ưu tiên để tạo bản sao có thể thay đổi của đối tượng không thể thay đổi được?

NSMutableSet * mutableSet = [ NSMutableSet setWithSet:nonMutableSet ] ; 

hoặc

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

Có sự khác biệt giữa hai hiện thực này? Là một "hiệu quả hơn" ở tất cả? (Các ví dụ khác sẽ là NSArray/NSMutableArray và NSDictionary/NSMutableDictionary

+0

Câu hỏi hay và tôi nghi ngờ có khả năng có nhiều tranh luận về vấn đề này. –

+0

Nếu bạn muốn làm tất cả mọi người một ưu tiên, chuẩn nó và trả lời câu hỏi cho mình :) Tôi nghi ngờ không nên có nhiều sự khác biệt, mặc dù. – fzwo

+0

@fzwo Tôi đoán tôi có thể làm điều đó .. Mặc dù đó là một phần câu hỏi triết lý lập trình :) – nielsbot

Trả lời

7

vui Benchmark :)

#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; 
} } 

Trên máy tính của tôi (10.7), setWithSet: là ~ 3x chậm hơn so với -mutableCopy (Có ai đó muốn thử trên iOS 5? :))

Bây giờ, câu hỏi đặt ra là: tại sao?

-mutableCopy đang dành phần lớn thời gian của mình trong CFBasicHashCreateCopy() (xem CFBasicHash.m). Điều này có vẻ như đang sao chép các nhóm băm trực tiếp, không có phục hồi.

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 liệt kê thông qua mỗi giá trị của tập hợp và sau đó thêm nó vào bộ mới. Từ việc thực hiện CFBasicHashAddValue (một lần nữa trong CFBasicHash.m), có vẻ như nó đang khôi phục từng giá trị trong tập hợp.

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 

Việc khôi phục này có ý nghĩa ở cấp CFSet. CFSets lấy CFSetHashCallBack trong tham số callBacks; do đó, hai CFSets của CFNumbers có thể có một quy trình băm khác nhau được chỉ định. NSSet của Foundation sử dụng CFSet dưới mui xe, và có hàm CFSetHashCallBack gọi -[NSObject hash]. (Mặc dù tôi đoán rằng Apple có thể tối ưu hóa trường hợp này và tránh rehash khi hai bộ có cùng một hàm gọi lại băm).

Lưu ý rằng điểm chuẩn này chỉ dành cho NSSet (của NSNumbers), các lớp thu thập khác có thể có các đặc tính hiệu suất khác nhau.

+0

Tôi tin rằng Mảng có thể có các triển khai sao lưu khác nhau (trong các lớp con riêng của nhóm lớp NSArray) tùy thuộc vào các trường hợp như số lượng mục làm phức tạp điểm chuẩn (nhưng nói chung cải thiện hiệu suất). – fzwo

+1

Yep! Ngoài ra, số lượng đối tượng trong bộ sưu tập cũng có thể tạo sự khác biệt. Cũng giống như một lưu ý, đối với mảng sử dụng điểm chuẩn ở trên, có vẻ như -mutableCopy/-autorelease hơi * chậm hơn * Những điều này thường xuyên được điều chỉnh - đó là một ý tưởng hay để làm lại các điểm chuẩn thường xuyên hơn so với các giả định về đặc tính hiệu suất của Foundation lớp học :) – iccir

+0

được tính là câu trả lời cho tôi! cảm ơn. – nielsbot

Các vấn đề liên quan