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' до конца