Какова стоимость использования авто-релиза в Какао? - PullRequest
11 голосов
/ 11 октября 2008

Кажется, что в большинстве документов Apple отсутствует использование автоматически выпущенных объектов, особенно при создании графических представлений, но я хочу знать, какова стоимость использования автоматически выпущенных объектов?

UIScrollView *timeline = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 34)];
[self addSubview:timeline];
[timeline release];

В конечном счете, должен ли я использовать стратегию, при которой все автоматически высвобождается, а использование retain / release должно быть исключением из правила для конкретных случаев? Или я вообще должен использовать retain / release с autorelease, являющимся исключением для возвращаемых объектов из вспомогательных методов, таких как [NSString stringWithEtc ...]?

Ответы [ 11 ]

21 голосов
/ 11 октября 2008

Есть две стоимости:

  1. (Предполагая, что у вас есть возможность избежать автоматического освобождения объектов.) Вы фактически излишне продлеваете срок службы ваших объектов. Это может означать, что ваш объем памяти увеличивается - без необходимости. На ограниченной платформе это может означать, что ваше приложение завершается, если оно превышает ограничение. Даже если вы не превысите лимит, это может привести к обмену вашей системы, что очень неэффективно.

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

На любой платформе рекомендуется избегать автоматического выпуска, если это возможно.

Чтобы ответить на вопросы:

В конечном счете, следует ли мне использовать стратегию, при которой все автоматически высвобождается, а использование retain / release должно быть исключением из правила для конкретных случаев?

Совсем наоборот.

Или я вообще должен использовать retain / release с autorelease, являющимся исключением для возвращаемых объектов из вспомогательных методов, таких как [NSString stringWithEtc ...]?

Вы должны всегда использовать retain / release, если можете - в случае NSString обычно нет необходимости использовать stringWithEtc методы, поскольку существует initWithEtc эквивалентов.

См. Также этот вопрос .

15 голосов
/ 12 октября 2008

Я должен не согласиться с Джимом Пулсом - я думаю, что , а не с использованием Autorelease делает отладку более сложной, потому что вы с большей вероятностью обнаружите, что случайно утечка памяти Конечно, статический анализатор Clang может обнаружить некоторые из этих случаев, но для меня небольшие накладные расходы при обычном использовании автоматического выпуска значительно затмеваются тем, что мой код менее подвержен ошибкам.

И тогда, только если у меня будет плотная петля, которую мне нужно оптимизировать, я начну смотреть на производительность. В противном случае это всего лишь преждевременная оптимизация, которая обычно считается плохой.

9 голосов
/ 11 октября 2008

Я удивлен, что никто еще не упомянул об этом. Самая большая причина избегать автоматически выпущенных объектов, когда вы можете не иметь никакого отношения к производительности. Да, все упомянутые здесь проблемы с производительностью абсолютно действительны, но самый большой недостаток автоматического выпуска заключается в том, что это значительно затрудняет отладку.

Если у вас есть перевыпущенный объект, который никогда не выпускается автоматически, его легко отследить. Если у вас есть сообщение о сбое, о котором периодически сообщают пользователи, и происходит обратная трассировка где-то к югу от NSPopAutoreleasePool, удачи ...

8 голосов
/ 22 октября 2008

В настоящее время я обычно использую объекты с автоматическим выпуском, потому что они приводят к более простому и легкому для чтения коду. Вы объявляете и инициализируете их, затем позволяете выпасть из области видимости. Механически они существуют немного дольше, но с точки зрения человека, пишущего код, это эквивалентно объявленному в стеке объекту в C ++, автоматически уничтожаемому, когда функция возвращается и ее фрейм уничтожается.

Несмотря на потерю эффективности, в большинстве случаев она незначительна. Чем больше проблема, тем больше объектов сохранилось, и последующее восстановление памяти может привести к более фрагментированному адресному пространству. Если это проблема, обычно довольно просто пойти и переключиться на ручное сохранение / отпускание несколькими горячими методами и улучшить его.

Как уже говорили другие, удобочитаемость превосходит производительность в коде, не чувствительном к производительности. Существует ряд случаев, когда использование автоматически выпущенных объектов приводит к большей фрагментации памяти, но в любом случае, когда объект переживет пул, он этого не сделает. В этих случаях единственная цена, которую вы платите, - это найти стоимость поиска правильного пула автоматического выпуска.

7 голосов
/ 22 октября 2008

Одно преимущество при использовании пулов авто-релиза заключается в том, что они безопасны для исключений без использования @try / @finally. У Грега Паркера («Мистер Objective-C») есть отличный пост , объясняющий детали этого.

Я склонен использовать autorelease в качестве меньшего количества кода и делает его более читабельным, IMO. Недостатком, как отмечали другие, является то, что вы продлеваете время жизни объектов, таким образом временно используя больше памяти. На практике мне пока не приходилось сталкиваться с чрезмерным использованием autorelease в любом написанном мною приложении Mac. Если высокая загрузка памяти кажется проблемой (которая не вызвана подлинной утечкой), я просто добавляю больше пулов автоматического выпуска (после профилирования, чтобы показать, где они мне нужны). Но, в общем, это довольно редко. Как показывает пост Майка Эша (Грэм Ли связан с ним), пулы авто-релизов имеют очень мало накладных расходов и работают быстро. Практически нулевая стоимость добавления дополнительных пулов автоматического выпуска.

Конечно, это все для приложений Mac. В приложениях для iPhone, где память более ограничена, вы можете быть осторожны при использовании автоматического выпуска. Но, как всегда, сначала пишите читаемый код, а затем оптимизируйте, , измеряя , где медленные / интенсивно использующие память части.

6 голосов
/ 11 октября 2008

Стоимость:

  1. Время, чтобы найти пул автоматического выпуска текущего потока и добавить в него объект.
  2. Память, занимаемая объектом до тех пор, пока он не будет освобожден в более поздний момент.

Если вы хотите быть очень консервативным в использовании памяти, вам следует избегать автоматического выпуска. Тем не менее, это полезный метод, который может сделать код более читабельным. Обязательное использование retain / release относится к категории «преждевременной оптимизации».

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

Время, когда следует опасаться авто-релиза, - это когда вы находитесь в цикле. Например, вы перебираете адресную книгу пользователя и, возможно, загружаете файл изображения для каждой записи. Если все эти объекты изображений будут автоматически освобождены, они будут накапливаться в памяти до тех пор, пока вы не посетите всю адресную книгу. Если адресная книга достаточно велика, вам может не хватить памяти. Если вы выпустите изображения, как только закончите с ними, в цикле ваше приложение может перезапустить память.

Если вы не можете избежать автоматического высвобождения внутри цикла (это выполняется кодом, который вы не написали и не можете изменить), вы также можете самостоятельно управлять NSAutoreleasePool внутри цикла.

Итак, помните об использовании автоматического освобождения внутри циклов (или методов, которые можно вызывать из циклов), но не избегайте этого, когда это может сделать код более читабельным.

2 голосов
/ 12 октября 2008

Другие ответили, следует ли вам делать авто-релиз, но когда вы должны авто-релиз, истощите рано и истощите часто: http://www.mikeash.com/?page=pyblog/autorelease-is-fast.html

2 голосов
/ 11 октября 2008

Насколько я понимаю, основным недостатком использования автоматического выпуска является то, что вы не знаете, когда объект будет наконец выпущен и уничтожен. Это может привести к тому, что ваше приложение будет использовать гораздо больше памяти, чем нужно, если у вас есть много автоматически выпущенных объектов, которые находятся вокруг, но еще не выпущены.

1 голос
/ 15 октября 2008

Я заметил, что приведенный вами пример кода предназначен для iPhone. Apple особенно рекомендует избегать автоматически выпущенных объектов для приложений iPhone. Я не могу найти конкретные рассуждения, но они обсуждали этот вопрос на WWDC.

0 голосов
/ 30 марта 2010

Старая тема, но щепка для новых читателей.

Я использую autorelease против retain / release в зависимости от риска ошибок autorelease, специфичных для объекта, и размера объекта. Если я просто добавляю несколько крошечных UIImageViews или пару UILabels к моему представлению, авто-релиз делает код читаемым и управляемым. И когда представление удаляется и освобождается, эти подпредставления должны быть выпущены достаточно скоро.

Если, с другой стороны, мы говорим о UIWebView (высокий риск ошибок автозагрузки) или, конечно, о некоторых данных, которые должны быть постоянными до «смерти» объекта, сохранение / освобождение - путь .

Честно говоря, мои проекты еще не достигли такого большого размера, когда дополнительное «время пребывания» автоматически выпущенных объектов создало бы проблему с памятью. Для сложных приложений эта проблема законна.

В любом случае, я не думаю, что подход «один размер подходит всем» будет правильным. Вы используете любой подход - или комбинацию подходов - подходит для проекта, помня все факторы, упомянутые выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...