Подтвердить что ты не робот

Нюансы NSMutableArray initWithCapacity

Есть ли у кого-нибудь совет, как лучше всего инициализировать NSMutableArray, когда дело доходит до диктовки емкости? В документации упоминается, что "... хотя вы указываете размер при создании массива, указанный размер считается" подсказкой ", фактический размер массива равен 0." Так что...

1) Если я инициализирую большую емкость, чем обычно использую, мне не нужно беспокоиться о потерянной памяти?

2) Если я инициализируюсь с пропускной способностью, как правило, ниже, чем я использую, мне нужно беспокоиться о более тяжелом времени обработки, выделяя больше памяти для хранения дополнительных элементов?

Насколько влияет эта инициализированная производительность на производительность/использование памяти этого типа данных?

4b9b3361

Ответ 1

Является ли какое-либо пространство впустую, давая слишком большую емкость, на самом деле представляет собой деталь реализации, которую Apple намеренно не раскрывает. NSMutableArray - кластер классов, который означает, что вы фактически не получаете экземпляр NSMutableArray, а некоторый другой специализированный класс, следуя одному и тому же интерфейсу. И Apple не говорит вам, какой класс возвращается в этом случае и как он себя ведет. Так что трудно дать настоящие советы здесь.

Если вы действительно знаете, что в среднем вам понадобится емкость X, просто используйте его. В противном случае, если у вас нет проблем с производительностью, мне все равно будет не нужна емкость и просто используйте [NSMutableArray array]...

Ответ 2

Мэтт Галлахер написал довольно информативную статью о классах коллекции Cocoa, а также пару тестов (с и без initWithCapacity:, а также сравнение между классами)

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

Его тест (источник доступен) для NSMutableArray длиной 1,000,000 взял 0,582256 сек без емкости и просто 0,572139 сек с емкостью.

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

Я бы сказал, что в 99% случаев использования [NSMutableArray array] просто отлично. Однако, если вы действительно знаете фактический размер результирующего массива, это не помешает использовать [NSMutableArray arrayWithCapacity:].


И вот эта статья от Peter Ammon (который является разработчиком в Apples AppKit/Foundation team), демонстрируя несколько проницательных тестов:

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


Изменить (12 марта 2012 года):

Дополнительная информация о производительности инициализации массива из http://darkdust.net/writings/objective-c/nsarray-enumeration-performance

[...] я [= > DarkDust] также хотел узнать, отличается ли производительность в зависимости от того, как был создан массив. Я протестировал два разных метода:

  • Создайте массив C, который ссылается на экземпляры объекта и создает массив с помощью initWithObjects:count:.
  • Создайте NSMutableArray и затем добавьте объекты, используя addObject:.

[...] есть разница при распределении: метод initWithObjects:count: быстрее. При очень большом числе объектов эта разница может стать значимой.


Изменить (6 марта 2014 года):

Дальнейшее понимание производительности инициализации массива из http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/:

Позволяет выделять новые массивы с начальной пропускной способностью, установленной на две последовательные мощности:

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

Сюрприз:

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