NSMutableArray initWithCapacity нюансы

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

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

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

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

2 ответа

Решение

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

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

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

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

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

Тест | Время
[Массив NSMutableArray]                     | 0,582256 секунд
[NSMutableArray arrayWithCapacity:1000000]                     | 0,572139 секунд
Перебор содержимого | 0,004713 секунд

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


И еще есть эта статья Питера Аммона (который является разработчиком в команде Apple AppKit/Foundation) с несколькими проницательными тестами:

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]);
}

Сюрприз Сюрприз:

размер: 2 // запрашиваемая емкость:1
размер: 2 // запрашиваемая емкость: 2
размер:  4 // запрашиваемая емкость: 4
размер:  8 // запрашиваемая емкость: 8
размер: 16 // запрашиваемая емкость:16
размер: 16 // запрашиваемая емкость:  32
размер: 16 // запрашиваемая емкость:  64
размер: 16 // запрашиваемая емкость: 128
...
// 'size: 16' до конца

Другие вопросы по тегам