NSMutableArray initWithCapacity nuances

Alguém tem conselhos sobre como melhor inicializar um NSMutableArray quando se trata de ditar a capacidade? A documentação menciona que “… mesmo que você especifique um tamanho ao criar uma matriz, o tamanho especificado é considerado como uma” dica “; o tamanho real da matriz ainda é 0.” Assim…

1) Se eu iniciar com uma capacidade maior do que normalmente uso, não tenho que me preocupar com memory desperdiçada?

2) Se eu iniciar com uma capacidade tipicamente menor do que eu uso, eu tenho que me preocupar com o tempo de processamento mais pesado alocando mais memory para manter os elementos extras?

Quão impactante é essa capacidade inicializada para o desempenho / uso de memory desse tipo de dados?

Se qualquer espaço é desperdiçado, ao dar uma capacidade muito grande, é realmente um detalhe de implementação que a Apple deliberadamente não expõe, eu acho. NSMutableArray é um cluster de class que significa que você não obtém uma instância de NSMutableArray, mas alguma outra class especializada seguindo a mesma interface. E a Apple não informa qual class é retornada e em qual caso ela está se comportando. Então é difícil dar conselhos reais aqui.

Se você realmente sabe que, em média, você precisará de uma capacidade de X , basta usá-lo. Caso contrário, a menos que você tenha problemas de desempenho, eu não me importaria com a capacidade e apenas usaria [NSMutableArray array]

Matt Gallagher escreveu um artigo bastante informativo sobre as aulas de coleção do Cocoa, junto com alguns benchmarks (com e sem initWithCapacity: bem como comparações entre classs)

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

Seu teste (fonte disponível) para um NSMutableArray de comprimento de 1.000.000 levou 0.582256sec sem capacidade e apenas 0.572139sec com capacidade .

 Teste |  Tempo
 [Matriz NSMutableArray] |  0,582256 segundos
 [NSMutableArray arrayWithCapacity: 1000000] |  0,572139 segundos
 Iterando o conteúdo |  0,004713 segundos

Eu diria que em 99% dos casos de uso [NSMutableArray array] está ótimo. Se você sabe o tamanho real da matriz resultante, no entanto, não vai doer usar [NSMutableArray arrayWithCapacity:] .


E depois há este artigo de Peter Ammon (que é desenvolvedor na equipe de AppKit / Foundation da Apple ), apresentando vários benchmarks perspicazes:

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


Editar (12 de março de 2012):

Mais informações sobre o desempenho de boot de matriz em http://darkdust.net/writings/objective-c/nsarray-enumeration-performance

[…] Eu [=> DarkDust] também queria saber se o desempenho é diferente dependendo de como o array foi criado. Eu testei dois methods diferentes:

  • Crie uma matriz C que faça referência às instâncias do object e crie a matriz usando initWithObjects:count:
  • Crie um NSMutableArray e subseqüentemente adicione objects usando addObject:

[…] Há uma diferença ao alocar: o método initWithObjects:count: é mais rápido . Com um número muito grande de objects , essa diferença pode se tornar significativa .


Editar (6 de março de 2014):

Mais informações sobre o desempenho de boot de array em http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/ :

Vamos alocar novos arrays com capacidade inicial definida para potências consecutivas de dois:

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

Surpresa surpresa:

 tamanho: 2 // capacidade solicitada: 1
 tamanho: 2 // capacidade solicitada: 2
 tamanho: 4 // capacidade solicitada: 4
 tamanho: 8 // capacidade solicitada: 8
 tamanho: 16 // capacidade solicitada: 16
 tamanho: 16 // capacidade solicitada: 32
 tamanho: 16 // capacidade solicitada: 64
 tamanho: 16 // capacidade solicitada: 128
 ...
 // 'tamanho: 16' todo o caminho