В ARC, по-прежнему целесообразно создавать @autoreleasepool для циклов?
Скажем, что у меня есть цикл, который возвращает кучу объектов с автореализованной NSData...
NSData* bigData = ...
while(some condition) {
NSData* smallData = [bigData subdataWithRange:...];
//process smallData
}
В ARC, должен ли я все-таки обернуть @autoreleasepool
вокруг условия while
?
NSData* bigData = ...
@autoreleasepool {
while(some condition) {
NSData* smallData = [bigData subdataWithRange:...];
//process smallData
}
}
Причина, по которой я спрашиваю, - это подсчет живых ассигнований в инструментах, проходящих через крышу для объектов NSData, которые вызывают метод dataWith...
, а не метод initWith...
. Когда я использую initWith...
, подсчет живого распределения намного меньше.
Лучше ли использовать методы initWith...
, когда это возможно?
Ответы
Ответ 1
Да, вы должны использовать пулы автозапуска при использовании удобных методов в узком цикле. Все старые правила управления памятью все еще применяются в ARC, компилятор просто вводит RR для вас. Оформить замечательный пост от удивительного Майка Эша!
Ссылка
Ответ 2
Я думаю, что ваша проблема заключается в том, что пул авторесурсов должен пройти внутри цикла. С петлей внутри блока авторекламы, а не наоборот, накопленные объекты не будут выпущены до завершения цикла.
Ответ 3
В ARC, должен ли я по-прежнему переносить @autoreleasepool вокруг условия while?
Да. Пулы Autorelease все еще на месте, и они растут и появляются по-прежнему. Компилятор просто добавляет и объединяет необходимые операции сохранения и освобождения при включенном ARC (эхо-вызове Logan) на основе методов, которые видны для TU и соглашений об именах по умолчанию.
Выполнение в ARC почти идентично подсчету ручной ссылки: стеки пулов Autorelease все еще существуют. Одно из отличий заключается в том, что компилятор может упорядочить операции подсчета ссылок, немного отличающиеся от того, как вы его написали (не ошибочно), и может опустить ненужные циклы сохранения.
Лучше ли использовать методы initWith... когда это возможно?
WRT минимизирует рост кучи по сравнению с автореализованными аналогами: Да. Это всегда было так. Это особенно важно на устройствах iOS, где память довольно ограничена.
Исключением является то, что объект может избежать выделения. Пример:
NSString * copy = [NSString stringWithString:arg];
в этом случае copy
может быть [[arg retain] autorelease]
. Обратите внимание, что в этом случае copy
все еще автореализован, но вы не должны, как правило, идти на большие длины, чтобы проверить наличие таких оптимизаций. Примечание. Здесь также лучше использовать copy = [arg copy]
... [arg release]
.
Другой бонус заключается в том, что ваш дисбаланс ref count часто улавливается ранее, когда объект никогда не автореализован, и ближе к сайту вызова (а не к тому, когда наконец будет добавлен пул Autorelease).
Производительность с большими пулами авторекламы на самом деле намного хуже, чем предполагалось большинством людей. Если вы можете в значительной степени избежать значительных изменений (например, используя alloc
+ init
... + release
), вы можете сделать вашу программу заметно быстрее. Явное создание пулов автоопределения дешево и может помочь свести к минимуму эту проблему. Когда распределения значительны и/или многочисленны, избегайте использования autorelease
на них, где это возможно, и оберните эти разделы в явные пулы автозавершения.