divertimento 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;
} }
Sulla mia macchina (10.7), setWithSet: è ~ 3 volte più lento di -mutableCopy (C'è qualcuno che vuole provare su iOS 5? :))
Ora, la domanda è: perché?
-mutableCopy sta trascorrendo la maggior parte del tempo in CFBasicHashCreateCopy() (vedere CFBasicHash.m). Sembra che copi direttamente i bucket hash, senza rehashing.
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 enumera attraverso ogni valore del set, e quindi aggiungendo al nuovo set. Dall'implementazione di CFBasicHashAddValue (sempre in CFBasicHash.m), sembra che stia rimodellando ogni valore nel set.
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
Questo rifacimento ha senso a livello CFSet. CFSet prende un CFSetHashCallBack nel parametro callBacks; quindi, due CFSet di CFNumbers potrebbero avere una routine di hashing diversa specificata. L'NSSet di Foundation utilizza CFSet sotto il cofano e ha una funzione CFSetHashCallBack che richiama -[NSObject hash]
. (Anche se penso che Apple potrebbe ottimizzare questo caso ed evitare il rehash quando due set hanno lo stesso callback hash).
Si noti che questo benchmark è solo per NSSet (di NSNumbers), altre classi di raccolta possono avere caratteristiche di prestazione diverse.
Buona domanda, e sospetto che ci potrebbe essere un sacco di dibattito su questo. –
Se vuoi fare un favore a tutti, confrontalo e rispondi tu stesso alla domanda :) Sospetto che non ci dovrebbe essere molta differenza, comunque. – fzwo
@fzwo Immagino di poterlo fare .. Sebbene sia in parte una questione di filosofia di programmazione :) – nielsbot