2009-08-20 11 views
10

Mi chiedo se questo influisce molto sulle prestazioni o sul consumo di memoria. Ho bisogno di un NSMutableArray e all'inizio posso solo immaginare quanti oggetti verranno aggiunti. Circa 3 a 5 forse. Quindi lo creo in questo modo:Quanto conta se creo un NSMutableArray con capacità = 3 invece di capacità = 50?

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

Cosa succede esattamente qui, quando lo si crea con una capacità di 3 anziché di 50, ad esempio? Sarebbe una cattiva idea crearlo con la capacità di 1, sapendo che ci saranno almeno 20 elementi? O non importa abbastanza da prendere qualche mal di testa su di esso? Ho 10 di questi array nella mia app e devono essere caricati tutti all'inizio.

risposta

6

initWithCapacity causerà lo spostamento di spazio per quel numero di elementi per NSMutableArray.

Se si inseriscono più dati nel NSMutableArray oltre tale capacità, NSMutableArray verrà riallocato. Questa riallocazione richiederà inoltre che l'intera matrice venga copiata dalla precedente (più piccola) allocazione a quella nuova (più grande). Quindi c'è una penalità di prestazioni per rendere questo numero troppo piccolo, ma non molto di uno.

Specificare una capacità superiore a quella che verrà effettivamente utilizzata, poiché la memoria allocata per gli elementi che non verranno mai utilizzati sarà esaurita.

La mia raccomandazione sarebbe che se si conosce la dimensione della matrice in genere non supererà N elementi, chiamare initWithCapacity:N. La penalità di prestazioni occasionali di NSMutableArray superiore a N è accettabile ed è una penalità che non dovrai pagare per quegli array che non superano tale limite.

+0

ottimi dettagli! anche le altre risposte erano grandiose. non è mai stato così difficile sceglierne uno come accettato. tutti votati ringrazia tutti! –

+2

Con tutto il rispetto, penso che questa risposta non sia corretta. Sebbene in determinati casi la capacità venga utilizzata per suggerire, non è vero che la creazione di un array mutabile con una capacità di un gigabyte alloca immediatamente un gigabyte di memoria. Se non mi credi, prova tu stesso. NSMutableArray * bigArray = [[NSMutableArray alloc] initWithCapacity: 1024 * 1024 * 1024]; if (! BigArray) { NSLog (@ "Array non è stato creato!"); } else { NSLog (@ "Sì, è stato creato."); } Se in realtà compili questo array, vedrai aumentare l'utilizzo della memoria. Non prima. – peterb

+0

La documentazione di initWithCapacity afferma che restituisce "un array inizializzato con sufficiente memoria per contenere oggetti numItems". Sembrerebbe esserci qualche discrepanza tra ciò che Peterb ha osservato e ciò che afferma la documentazione. – fbrereto

6

Non è un grosso problema a meno che non si parli di ripetizioni estreme o di enormi matrici. Non vale la pena provare a ottimizzare, a meno che non diventi un vero collo di bottiglia.

EDIT: Vorrei aggiungere una citazione da Donald Knuth:

ottimizzazione prematura è la radice di tutti i mali.

+0

che cosa vuol dire cosa prematura? Il mio inglese non è eccezionale ;-) per favore, spiegami. Grazie! –

+2

Significa: non ottimizzare le prestazioni del codice fino a quando ea) a) non ne ha davvero bisogno per funzionare più velocemente eb) identificare le parti lente. Altrimenti, semplicemente rendi il tuo codice più complicato, aggiungendo complessità e tempo di spesa senza alcun beneficio. –

+0

ha senso :-) –

3

C'è la risposta teorica e la risposta pratica. In teoria, l'impostazione di una capacità più grande può modificare l'allocazione e la strategia di archiviazione per l'array (sebbene chiamato internamente "NSArray", la struttura è un po 'più complessa di quella).

Da un punto di vista pratico, l'array verrà riallocato in base alle esigenze e con i numeri di cui si sta parlando dubito che ci sarebbe alcuna differenza di sorta. Potrei creare un arrayWithCapacity se sapessi che inserirò migliaia e migliaia di elementi. 3 contro 50 è sostanzialmente priva di significato.

L'utilizzo ottimale per "withCapacity" dal mio punto di vista è solo un ovvio punto di partenza per appendere le ipotesi, quindi è possibile (ad esempio) avere una documentazione in-code su qualcosa su cui si potrebbe voler affermare in futuro. ma non è assolutamente necessario.

Dal punto di vista pratico, il miglior utilizzo del tempo è quello di non pensare nemmeno al problema.

0

Anche se sicuramente non fa male a utilizzare initWithCapacity: come gli altri qui menzionati, si dovrebbe verificare this research sulle prestazioni di inizializzazione matrice da Bartosz Ciechanowski:

capacità iniziale quasi non importa

Assegniamo nuovi array con capacità iniziale impostata a due potenze consecutive:

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 
Problemi correlati