2010-10-16 15 views
26

Qualcuno ha consigli su come inizializzare al meglio un NSMutableArray quando si tratta di dettare la capacità? La documentazione menziona che "... anche se si specifica una dimensione quando si crea un array, la dimensione specificata è considerata un" suggerimento ", la dimensione effettiva dell'array è ancora 0." Quindi ...NSMutableArray initWithCapacità sfumature

1) Se avvio con una capacità superiore rispetto a quella che uso di solito, non devo preoccuparmi della memoria sprecata?

2) Se inizio con una capacità tipicamente inferiore a quella che uso, devo preoccuparmi del tempo di elaborazione più pesante allocando più memoria per contenere gli elementi extra?

Quanto incide questa capacità inizializzata sull'utilizzo delle prestazioni/della memoria di questo tipo di dati?

risposta

15

Se uno spazio è sprecato dando una capacità troppo grande è in realtà un dettaglio di implementazione che Apple non espone deliberatamente, suppongo. NSMutableArray è un cluster di classi che significa che in realtà non si ottiene un'istanza di NSMutableArray ma qualche altra classe specializzata che segue la stessa interfaccia. E Apple non ti dice quale classe viene restituita, nel qual caso e come si sta comportando. Quindi è difficile dare dei veri consigli qui.

Se davvero sai che in media hai bisogno di una capacità di X, basta usarlo. In caso contrario, se non avete problemi di prestazioni non mi preoccupano le capacità a tutti e basta usare [NSMutableArray array] ...

+0

Ma se si sa la capacità, allora perché utilizzare un array mutabile? Ci sono benefici oltre alla rimozione/aggiunta di oggetti? –

+2

Non è sempre possibile utilizzare un array non modificabile perché gli oggetti da aggiungere non sono sempre noti in anticipo. Ad esempio, supponiamo di voler aggiungere i numeri 1 ... x in un array ma _x_ è un argomento e quindi non è noto: dovrai aggiungere i numeri in un ciclo. Naturalmente, si può anche usare un array C e '- [NSArray initWithObjects: count:]' ma è troppo lavoro la maggior parte delle volte. – DarkDust

+0

In realtà non mi aspettavo una risposta, grazie per aver dedicato del tempo! Grandi informazioni –

40

Matt Gallagher ha scritto un articolo piuttosto informativo sulle classi di raccolta del cacao, insieme a un paio di punti di riferimento (con & senza initWithCapacity:, così come i confronti incrociati di classe)

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

la sua prova (sorgente disponibile) per un NSMutableArray di lunghezza 1.000.000 preso 0.582256sec senza capacità e solo 0,572139sec con capacità.

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

direi che nel 99% dei casi d'uso [NSMutableArray array] è bene. Se si conosce la dimensione effettiva della matrice risultante, tuttavia, non farà male usare [NSMutableArray arrayWithCapacity:].


E poi c'è questo articolo di Peter Ammon (che è uno sviluppatore sulla squadra AppKit/Fondazione di Apple) con diversi penetranti benchmark:

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


Modifica (12 marzo 2012):

un quadro più chiaro sulle prestazioni di inizializzazione matrice da http://darkdust.net/writings/objective-c/nsarray-enumeration-performance

[...] I [=> DarkDust] anche voluto sapere se la prestazione è diverso a seconda di come è stato creato l'array. Ho provato due metodi diversi:

  • Creare un array C che faccia riferimento alle istanze dell'oggetto e creare l'array utilizzando initWithObjects:count:.
  • Creare uno NSMutableArray e successivamente aggiungere oggetti utilizzando addObject:.

[...] v'è una differenza in sede di assegnazione: il metodo initWithObjects:count:è più veloce. Con un numero molto grande di oggetti, , questa differenza può essere significativa.


Edit (6a March 2014):

Ulteriori informazioni più dettagliate sulle prestazioni inizializzazione campo da http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/:

Poniamo allocare nuovi array con capacità iniziale impostata potenze consecutive di due:

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

Link eccellenti, grazie per l'intuizione. – DarkDust

+0

Hai un refuso: 'arraywithCapacity' dovrebbe essere' arrayWithCapacity'. – zekel

+0

@zekel, grazie risolto. – Regexident