2012-01-24 15 views
5

Hay 2 opciones (posiblemente más). Usando NSSet como ejemplo:¿Forma preferida de hacer una copia mutable de un objeto no mutable?

NSMutableSet * mutableSet = [ NSMutableSet setWithSet:nonMutableSet ] ; 

o

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

¿Hay alguna diferencia entre estas dos implementaciones? ¿Es uno "más eficiente" en absoluto? (Otros ejemplos serían NSArray/NSMutableArray y NSDictionary/NSMutableDictionary

+0

Buena pregunta, y sospecho que podría ser potencialmente un gran debate sobre esto. –

+0

Si le gustaría hacer un favor a todo el mundo, comparta y responda la pregunta usted mismo :) Sin embargo, sospecho que no debería haber mucha diferencia. – fzwo

+0

@fzwo supongo que podría hacer eso .. Aunque es en parte una cuestión filosofía de programación :) – nielsbot

Respuesta

7

diversión 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; 
} } 

En mi máquina (10.7), setWithSet: es ~ 3 veces más lento que -mutableCopy (¿Alguien quiere probar ? en iOS 5 :))

Ahora, la pregunta es: ¿por qué?

-mutableCopy está pasando la mayor parte de su tiempo en CFBasicHashCreateCopy() (ver CFBasicHash.m). Esto parece estar copiando los cubos de hash directamente, sin reiniciar.

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 cada valor del conjunto y luego lo agrega al nuevo conjunto. Desde la implementación de CFBasicHashAddValue (nuevamente en CFBasicHash.m), parece que está volviendo a generar cada valor en el conjunto.

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 

Esta repetición tiene sentido en el nivel CFSet. CFSets toma un CFSetHashCallBack en el parámetro callBacks; por lo tanto, dos CFSets de CFNumbers podrían tener una rutina de hash diferente especificada. El NSSet de Foundation utiliza CFSet debajo del capó y tiene una función CFSetHashCallBack que invoca -[NSObject hash]. (Aunque supongo que Apple podría optimizar este caso y evitar la repetición cuando dos conjuntos tienen la misma devolución de llamada hash).

Tenga en cuenta que este punto de referencia es para NSSet (de NSNumbers) solamente, otras clases de colección puede tener diferentes características de rendimiento.

+0

creo matrices pueden tener diferentes implementaciones de respaldo (en las subclases privadas del clúster clase NSArray) dependiendo de las circunstancias, tales como el número de artículos, que además complica el benchmarking (pero generalmente mejora el rendimiento). – fzwo

+1

¡Sip! Además, la cantidad de objetos en la colección puede hacer una diferencia también. Así como una nota, para las matrices utilizando el punto de referencia más arriba, parece que -mutableCopy/-autorelease es ligeramente más lento * * Estas cosas están sintonizados con frecuencia - es una buena idea para hacer de nuevo los puntos de referencia siempre tan a menudo que hacer suposiciones acerca de las características de funcionamiento de la Fundación clases :) – iccir

+0

cuenta como una respuesta para mí! Gracias. – nielsbot

Cuestiones relacionadas