2009-08-20 18 views
10

Me pregunto si esto afecta mucho el rendimiento o el consumo de memoria. Necesito un NSMutableArray, y al principio solo puedo adivinar cuántos objetos se agregarán. Alrededor de 3 a 5 tal vez. Así que lo creo así:¿Cuánto importa si creo un NSMutableArray con capacidad = 3 en lugar de capacidad = 50?

NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:3]; 

¿Qué sucede exactamente aquí, al crearlo con una capacidad de 3 en lugar de 50, por ejemplo? ¿Sería una mala idea crearlo con una capacidad de 1, sabiendo que habrá al menos 20 elementos? ¿O eso no es lo suficientemente importante como para causarle dolores de cabeza? Tengo 10 de estas matrices en mi aplicación y todas tienen que cargarse al inicio.

Respuesta

6

initWithCapacity causará NSMutableArray preasignar espacio para esa cantidad de elementos.

Introduciendo más datos en su NSMutableArray más allá de esa capacidad causará que NSMutableArray reasigne su memoria subyacente. Esta reasignación también requerirá que toda la matriz se copie de la asignación anterior (más pequeña) a la nueva (más grande). Por lo tanto, hay una penalización en el rendimiento por hacer que este número sea demasiado pequeño, pero no mucho de uno.

Al especificar una capacidad mayor que la que realmente utilizará, desperdicia memoria, ya que habrá memoria asignada para los elementos que nunca se utilizarán.

Mi recomendación sería que, si sabes que el tamaño de tu matriz normalmente no excederá de N elementos, llama al initWithCapacity:N. La penalización de rendimiento de ocasionales NSMutableArray mayor que N es aceptable, y es una penalización que no tendrá que pagar por aquellas matrices que no exceden ese límite.

+0

¡grandes detalles! las otras respuestas también fueron geniales. nunca fue tan difícil elegir uno como aceptado. todos votaron. ¡gracias a todos! –

+2

Con todo respeto, creo que esta respuesta es incorrecta. Aunque la capacidad se utiliza para dar pistas en ciertos casos, no es el caso que al crear una matriz mutable con una capacidad de un gigabyte se asigne inmediatamente un gigabyte de memoria. Si no me crees, pruébalo tú mismo. NSMutableArray * bigArray = [[NSMutableArray alloc] initWithCapacity: 1024 * 1024 * 1024]; if (! BigArray) { NSLog (@ "¡La matriz no se creó!"); } else { NSLog (@ "Sí, se creó."); } Si realmente LLENAS esta matriz, verás un aumento en el uso de la memoria. No antes. – peterb

+0

La documentación de initWithCapacity indica que devuelve "una matriz inicializada con suficiente memoria para contener objetos numItems". Parecería haber alguna discrepancia entre lo que peterb ha observado y lo que afirma la documentación. – fbrereto

6

No es un gran problema a menos que esté hablando de una repetición extrema o matrices enormes. No vale la pena tratar de optimizar a menos que se convierta en un verdadero cuello de botella.

EDIT: Me gustaría añadir una cita de Donald Knuth:

optimización prematura es la raíz de todo mal.

+0

lo que quiere decir algo prematura? Mi inglés no es tan bueno ;-) por favor explica. ¡Gracias! –

+2

Significa: no optimice el rendimiento de su código hasta que, a menos que a) realmente lo necesite, y b) identifique las partes lentas. De lo contrario, simplemente hace que su código sea más complicado, agregando complejidad y gastando tiempo sin ningún beneficio. –

+0

tiene sentido :-) –

3

Existe la respuesta teórica y la respuesta práctica. En teoría, establecer una capacidad más grande puede cambiar la estrategia de asignación y almacenamiento para la matriz (aunque llamada internamente "NSArray", la estructura es un poco más compleja que eso).

Desde un punto de vista práctico, la matriz se reasignará según sea necesario y con los números de los que está hablando, dudo que haya alguna diferencia en absoluto. Podría hacer un arrayWithCapacity si supiera que pondré miles y miles de elementos. 3 vs. 50 es esencialmente insignificante.

El mejor uso para "withCapacity" desde mi perspectiva es simplemente proporcionar un gancho obvio para colgar sus suposiciones, por lo que podría (por ejemplo) tener documentación en código de algo sobre lo que más tarde podría querer afirmar. pero de ninguna manera es obligatorio.

Desde una perspectiva práctica, el mejor uso de su tiempo es ni siquiera pensar en el problema.

0

A pesar de que definitivamente no hace daño a utilizar initWithCapacity: como otros mencionados aquí, que debe salir this research el rendimiento de la matriz de inicialización de Bartosz Ciechanowski:

La capacidad inicial casi no importa

Vamos a asignar nuevas matrices con capacidad inicial para establecer 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 
Cuestiones relacionadas