эталон веселья! :)
#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: примерно в 3 раза медленнее, чем -mutableCopy (кто-то хочет попробовать на iOS 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
Эта перефразировка имеет смысл на уровне CFSet. CFSets принимает CFSetHashCallBack в параметре callBacks; таким образом, два набора CFSets номеров CFN могут иметь различную заданную процедуру хеширования. NSSet Фонда использует CFSet скрытно и имеет функцию CFSetHashCallBack, которая вызывает -[NSObject hash]
. (Хотя я предполагаю, что Apple могла бы оптимизировать этот случай и избежать перефразирования, когда два набора имеют одинаковый обратный вызов хеша).
Обратите внимание, что этот тест предназначен только для NSSet (из NSNumbers), другие классы сбора могут иметь другие характеристики производительности.