2009-08-20 10 views
10

Zastanawiam się, czy ma to wpływ na wydajność lub zużycie pamięci. Potrzebuję NSMutableArray i na początku mogę tylko zgadywać, ile obiektów zostanie dodanych. Około 3 do 5 może. Stworzyłem go w ten sposób:Ile to ma znaczenie, jeśli utworzę NSMutableArray o pojemności = 3 zamiast o pojemności = 50?

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

Co dzieje się tutaj dokładnie, podczas tworzenia go o pojemności 3 zamiast 50 na przykład? Czy byłoby złym pomysłem utworzenie go o pojemności 1, wiedząc, że będzie co najmniej 20 elementów? Czy to nie ma znaczenia, aby trochę bóle głowy na to? Mam 10 takich tablic w mojej aplikacji i wszystkie muszą się załadować na starcie.

Odpowiedz

6

initWithCapacity spowoduje, że NSMutableArray zwolni miejsce dla tej liczby elementów.

Przesunięcie większej ilości danych do swojej NSMutableArray powyżej tej pojemności spowoduje, że NSMutableArray ponownie przydzieli pamięć podstawową. Ta realokacja będzie również wymagać skopiowania całej tablicy ze starej (mniejszej) alokacji na nową (większą). Występuje więc kara za wydajność, która sprawia, że ​​liczba ta jest zbyt mała, ale niewiele z nich.

Określanie pojemności większej niż ilość zużywanej pamięci, ponieważ pamięć zostanie przydzielona dla elementów, które nigdy nie będą używane.

Moja rekomendacja byłaby taka, że ​​jeśli wiesz, że rozmiar Twojej tablicy zwykle nie przekroczy N pozycji, zadzwoń pod numer initWithCapacity:N. Kary za wydajność okazjonalne NSMutableArray większe niż N są dopuszczalne, a to kara, której nie będziesz musiał płacić za te tablice, które nie przekroczą tego limitu.

+0

świetne szczegóły! inne odpowiedzi też były świetne. uznał, że nigdy nie jest tak trudne, aby wybrać jeden zaakceptowany. wszyscy głosowali w górę. Dziękuje wszystkim! –

+2

Z całym szacunkiem, myślę, że ta odpowiedź jest błędna. Mimo że w niektórych przypadkach pojemność jest wykorzystywana do podpowiedzi, to nie jest tak, że utworzenie tablicy zmiennych o pojemności gigabajta natychmiast przydzieli gigabajt pamięci. Jeśli mi nie wierzysz, spróbuj sam. NSMutableArray * bigArray = [[NSMutableArray alloc] initWithCapacity: 1024 * 1024 * 1024]; if (! BigArray) { NSLog (@ "Array was not created!"); } else { NSLog (@ "Tak, został utworzony."); } Jeśli faktycznie wypełnisz tę tablicę, zobaczysz wzrost wykorzystania pamięci. Nie przed. – peterb

+0

Dokumentacja dla initWithCapacity stwierdza, że ​​zwraca "tablicę zainicjowaną z wystarczającą pamięcią do przechowywania obiektów numItems." Wydaje się, że istnieją pewne rozbieżności między tym, co zaobserwował Peterb a tym, co twierdzi dokumentacja. – fbrereto

6

To nie jest wielka sprawa, chyba że mówisz o ekstremalnych powtórzeniach lub olbrzymich tablicach. Nie warto próbować optymalizacji, chyba że stanie się prawdziwym wąskim gardłem.

EDIT: Chciałbym dodać cytat z Donalda Knuth:

Przedwczesna optymalizacja jest źródłem wszelkiego zła.

+0

co to ma oznaczać przedwczesny rzeczą? Mój angielski nie jest taki wspaniały ;-) proszę wyjaśnić. dzięki! –

+2

Oznacza to: nie optymalizuj wydajności kodu, dopóki (a) naprawdę nie potrzebujesz go uruchamiać szybciej i b) rozpoznaj wolne części. W przeciwnym razie po prostu sprawisz, że kod będzie bardziej skomplikowany, co zwiększy złożoność i skróci czas spędzany bez żadnych korzyści. –

+0

ma sens :-) –

3

Istnieje teoretyczna odpowiedź i praktyczna odpowiedź. Teoretycznie ustawienie większej pojemności może zmienić strategię alokacji i przechowywania dla macierzy (chociaż jest ona nazywana "NSArray" wewnętrznie, struktura jest nieco bardziej skomplikowana).

Z praktycznego punktu widzenia tablica będzie ponownie przydzielana w razie potrzeby, z liczbami, o których mówisz, i wątpię, by były jakiekolwiek różnice. Mogę zrobić tablicęWithCapacity, gdybym wiedział, że będę wkładał tysiące na tysiące przedmiotów. 3 na 50 jest zasadniczo bez znaczenia.

Najlepszym zastosowaniem dla "withCapacity" z mojej perspektywy jest dostarczenie oczywistego haczyka, na którym można zawiesić swoje założenia, abyś mógł (na przykład) mieć dokumentację wewnątrz kodu czegoś, co możesz później chcieć potwierdzić. ale w żadnym wypadku nie jest to wymagane.

Z praktycznego punktu widzenia najlepiej wykorzystać czas, aby nie myśleć o problemie.

0

Choć na pewno nie zaszkodzi użyć initWithCapacity: jak inni wymienionych tutaj, powinieneś sprawdzić this research na wydajność inicjalizacji tablicy od Bartosz Ciechanowski:

pojemność początkowa prawie nie ma znaczenia

Przydzielmy nowe tablice z początkową pojemnością ustawioną na następujące po sobie potęgi:

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

niespodzianka:

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 
Powiązane problemy