2010-10-16 20 views
26

¿Alguien tiene consejos sobre cómo inicializar mejor un NSMutableArray a la hora de dictar la capacidad? La documentación menciona que "... aunque especifique un tamaño cuando crea una matriz, el tamaño especificado se considera como una" pista ", el tamaño real de la matriz sigue siendo 0." Entonces ...NSMutableArray initWithCapacity matices

1) Si inicio con una capacidad mayor a la que suelo usar, ¿no tengo que preocuparme por la pérdida de memoria?

2) Si inicio con una capacidad típicamente inferior a la que uso, ¿tengo que preocuparme por un mayor tiempo de procesamiento asignando más memoria para contener los elementos adicionales?

¿Qué tan impactante es esta capacidad inicializada para el rendimiento/uso de la memoria de este tipo de datos?

Respuesta

15

Si un espacio se desperdicia dando una capacidad demasiado grande es en realidad un detalle de implementación que Apple deliberadamente no expone, supongo. NSMutableArray es un clúster de clase, lo que significa que en realidad no se obtiene una instancia de NSMutableArray sino otra clase especializada siguiendo la misma interfaz. Y Apple no te dice qué clase devuelve en qué caso y cómo se comporta. Entonces es difícil dar consejos reales aquí.

Si realmente sabe que, en promedio, necesitará una capacidad de X, simplemente úselo. De lo contrario, a menos que tenga problemas de rendimiento no me importa la capacidad en absoluto y sólo tiene que utilizar [NSMutableArray array] ...

+0

Pero si conoce la capacidad, entonces ¿por qué utilizar una matriz mutable? ¿Hay otros beneficios además de eliminar/agregar objetos? –

+2

No siempre se puede usar una matriz no mutable porque los objetos para agregar no siempre se conocen de antemano. Por ejemplo, supongamos que desea agregar los números 1 ... x a una matriz, pero _x_ es un argumento y, por lo tanto, no se sabe: tendrá que agregar los números en un bucle. Por supuesto, también puede usar una matriz C y '- [NSArray initWithObjects: count:]' pero eso es demasiado trabajo la mayor parte del tiempo. – DarkDust

+0

No esperaba una respuesta, ¡gracias por tomarse el tiempo! Buena información –

40

Matt Gallagher ha escrito un artículo muy informativo sobre las clases de colección de cacao, junto con un par de puntos de referencia (con & sin initWithCapacity:, así como comparaciones entre clases)

http://cocoawithlove.com/2008/08/nsarray-or-nsset-nsdictionary-or.html

Su prueba (fuente disponible) para un NSMutableArray de longitud 1.000.000 tomó 0.582256sec sin capacidad y solo 0.572139seg con capacidad.

 
Test          | Time 
[NSMutableArray array]      | 0.582256 seconds 
[NSMutableArray arrayWithCapacity:1000000] | 0.572139 seconds 
Iterating contents       | 0.004713 seconds 

Yo diría que en el 99% de los casos de uso [NSMutableArray array] está muy bien. Sin embargo, si conoces el tamaño real de la matriz resultante, no va a doler usar [NSMutableArray arrayWithCapacity:] tampoco.


Y luego está este artículo por Peter Ammon (que es un desarrollador en el equipo AppKit/Fundación de Apple) que ofrece varias interesantes puntos de referencia:

http://ridiculousfish.com/blog/archives/2005/12/23/array/


Editar (12 de marzo de 2012):

Una visión más clara sobre el rendimiento de inicialización de la matriz de http://darkdust.net/writings/objective-c/nsarray-enumeration-performance

[...] I [=> DarkDust] También quería saber si el rendimiento es diferente dependiendo de cómo se creó la matriz. Probé dos métodos diferentes:

  • Cree una matriz C que haga referencia a las instancias del objeto y cree la matriz usando initWithObjects:count:.
  • Crea un NSMutableArray y luego agrega objetos usando addObject:.

[...] hay una diferencia en la asignación: el método es más rápido initWithObjects:count:. Con un número muy grande de objetos , esta diferencia puede convertirse en significativo.


Editar (6 ° de marzo de 2014):

Además visión más clara sobre el rendimiento de inicialización de la matriz de http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/:

Vamos a asignar nuevas matrices con una capacidad inicial se establece en potencias consecutivas de dos:

for (int i = 0; i < 16; i++) { 
    NSLog(@"%@", [[[NSMutableArray alloc] initWithCapacity:1 << i] explored_description]); 
} 

Sorpresa sorpresa:

 
size: 2 // requested capacity: 1 
size: 2 // requested capacity: 2 
size: 4 // requested capacity: 4 
size: 8 // requested capacity: 8 
size: 16 // requested capacity: 16 
size: 16 // requested capacity: 32 
size: 16 // requested capacity: 64 
size: 16 // requested capacity: 128 
... 
// 'size: 16' all the way down 

+1

Excelentes enlaces, gracias por la información. – DarkDust

+0

Tiene un error tipográfico: 'arraywithCapacity' debe ser' arrayWithCapacity'. – zekel

+0

@zekel, gracias arreglado. – Regexident