Под ARC все еще целесообразно создать цикл @autoreleasepool для циклов? - PullRequest
19 голосов
/ 19 октября 2011

Допустим, у меня есть цикл, который возвращает кучу автоматически выпущенных объектов 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...?

Ответы [ 3 ]

13 голосов
/ 19 октября 2011

Я думаю, что ваша проблема в том, что пул авто-релизов должен идти внутри циклаС циклом внутри блока автоматического выпуска, а не наоборот, накопленные объекты не будут освобождены, пока цикл не завершится.

13 голосов
/ 19 октября 2011

Да, вы все равно должны использовать пулы автоматического освобождения при использовании удобных методов в узком цикле. Все старые правила управления памятью все еще применяются в ARC, компилятор просто вводит для вас RR. Зацените отличный пост от удивительного Майка Эша!

Ссылка

7 голосов
/ 19 октября 2011

Под ARC, я должен все еще обернуть @autoreleasepool вокруг условия while?

Да. Автозапуск Бассейны все еще на месте, и растут и всплывают как прежде. Компилятор просто добавляет и объединяет необходимые операции сохранения и освобождения, когда ARC включен (повторяет логан), на основе методов, которые видимы для TU, и соглашений об именах по умолчанию.

Выполнение в ARC практически идентично ручному подсчету ссылок: стеки пулов автоматического выпуска все еще существуют. Одно из отличий состоит в том, что компилятор может упорядочить операции подсчета ссылок несколько отличным от того, как вы его написали (не неправильно), и может пропустить ненужные циклы сохранения.

Лучше ли, когда это возможно, предпочитать методы initWith ...

WRT, минимизирующий рост кучи по сравнению с автоматически выпущенными аналогами: Да. Это всегда было так. Это особенно важно на устройствах iOS, где память довольно ограничена.

Исключением является случай, когда объект может избежать выделения. Пример:

NSString * copy = [NSString stringWithString:arg];

в этом случае copy может быть [[arg retain] autorelease]. Обратите внимание, что в этом случае copy по-прежнему автоматически высвобождается, но обычно не стоит слишком долго проверять наличие таких оптимизаций. Примечание: здесь также лучше использовать copy = [arg copy] ... [arg release].

Другим бонусом является то, что дисбалансы вашего счета часто обнаруживаются раньше, когда объект никогда не освобождается автоматически, и ближе к месту вызова (а не тогда, когда пул автоматического освобождения окончательно выталкивается).

Производительность с большими пулами авто-релизов на самом деле намного хуже, чем может показаться большинству людей. Если вы можете избежать их сильной зависимости (например, используя alloc + init ... + release), вы можете значительно ускорить свою программу. Явное создание пулов автоматического выпуска является дешевым и может помочь минимизировать эту проблему. Если выделения велики и / или многочисленны, по возможности избегайте использования на них autorelease и оборачивайте эти разделы в явные пулы автоматического выпуска.

...