Пул автоматического выпуска программирования для iOS

В документации Apple это говорит:

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

Это должно быть очевидно, но я все равно попрошу подтверждения.

Если я разрабатываю то, что в конечном итоге станет фоновым процессом (через Grand Central Dispatch), но для простоты я сначала просто помещаю его в viewDidLoad самого первого загружаемого представления, чтобы мое представление фактически не отображалось на экране до тех пор, пока все, что (скажем) 2 минуты обработки выполнено, затем в течение этих двух минут весь этот пул автовыпуска по умолчанию никогда не освобождается, потому что он еще не прошел итерацию цикла событий, верно? Было бы просто безумием услышать «нет», но я застрял в этой растущей проблеме с памятью, поэтому я собираюсь попросить подтверждения и надеяться на хорошие новости.

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


person huggie    schedule 31.08.2012    source источник
comment
Я предполагаю, что вы не используете ARC, верно?   -  person 8vius    schedule 31.08.2012
comment
По крайней мере, в Xcode 3, если вы запустите свое приложение в эмуляторе и создадите объект с автовыпуском, в котором в стеке нет пула автовыпуска, эмулятор выведет предупреждение в консоль в следующих строках: Не определен пул автовыпуска - - просто утечка объекта xxx. Может быть непросто определить, откуда они исходят, но это очень полезное сообщение, чтобы убедиться, что вы его не получаете.   -  person Hot Licks    schedule 31.08.2012


Ответы (2)


Я постараюсь дать вам полный ответ на оба ваших вопроса.

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

Насчет НОД вопроса я бы сказал нет. Вам не нужно создавать пул автоматического выпуска при работе с GCD. Обычно, как также написано в Вы нужно создать NSAutoreleasePool внутри блока в GCD?, GCD автоматически управляет пулом авторелиза для каждой очереди. Итак, если у вас мало объектов, вам не нужно об этом беспокоиться, но если вы создаете их много, да, создайте пул автоматического освобождения. Последнее также позволяет уменьшить объем памяти.

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

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

Цель использования потока — сделать приложение более отзывчивым, но это может привести к различным проблемам, таким как несогласованность данных (состояние гонки) или взаимоблокировки.

Для получения дополнительной информации я действительно рекомендую прочитать Пого-стик NSRunLoop, Понимание NSRunLoop и NSDefaultRunLoopMode vs NSRunLoopCommonModes.

person Lorenzo B    schedule 31.08.2012
comment
Мне нужно уточнение вашего объяснения. Итак, все эти две минуты, когда приложение не будет отвечать, это когда цикл не закончился, и пул не будет слит в течение этих двух минут, верно? - person huggie; 01.09.2012
comment
@huggie Я расширил свой ответ. Надеюсь, поможет. - person Lorenzo B; 01.09.2012
comment
Здорово! Я ценю вашу помощь! Я поставил больше блоков автоматического освобождения, и теперь моя программа проходит весь процесс без рвоты. Теперь инструменты сообщают, что использование оперативной памяти во время моих измерений сократилось до 2 МБ, а монитор активности OS X показывает использование ОЗУ около 70 МБ, тогда как раньше для этого требовался колоссальный 1 ГБ ОЗУ. - person huggie; 01.09.2012

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

Таким образом, единственный вопрос — это волшебное слово «в конце концов». Во время обработки ваше приложение использует слишком много памяти (например, так много памяти, что система уничтожит его) из-за автоматически выпущенных объектов, которые еще не были выпущены? Помните, что они будут освобождены; вопрос в том, настолько ли ситуация плоха, что вам нужно выпустить их сейчас, не дожидаясь опустошения пула автовыпуска, что наверняка произойдет без каких-либо действий с вашей стороны .

Только Инструменты могут сказать вам, так что не гадайте и не оптимизируйте преждевременно; посмотрите, что покажет Instruments. Если ситуация настолько плоха, то, конечно же, найдите цикл, который генерирует все эти автоматически освобождаемые объекты, и поместите в него блок автоматического освобождения, чтобы пул сливался каждый раз в цикле. В противном случае действительно нет необходимости. (С другой стороны, в ARC блок автоосвобождения добавляет очень мало накладных расходов, поэтому преждевременная оптимизация, вероятно, не причинит большого вреда.)

person matt    schedule 31.08.2012
comment
Затраты на создание/управление пулом автоматического выпуска минимальны, поэтому нет никакой реальной опасности в том, чтобы быть немного чрезмерным в их использовании, при условии соблюдения правильности (т. е. вы не выполняете автоматический выпуск слишком рано). В частности, там, где есть относительно продолжительный цикл, который будет создавать множество локальных объектов, может быть целесообразно добавить диапазон автоосвобождения без предварительной инструментальной обработки. - person Hot Licks; 31.08.2012
comment
Ну, дело в том, что при работе в моем симуляторе он работает до такой степени, что больше не может выделять! Так что да, он использует слишком много памяти. Я думаю, что мне, вероятно, нужно изменить все эти вызовы stringWithFormat, например, на initWithFormat. Или мне нужен собственный блок авторелиза. - person huggie; 01.09.2012
comment
@huggie - initWithFormat не принесет пользы (на самом деле будет хуже), если у вас нет где-то соответствующего release. - person Hot Licks; 01.09.2012
comment
@HotLicks У этого проекта есть ARC, поэтому я не буду писать release. Но я вижу его как то же самое только в том случае, если он мне действительно нужен и держит его при себе. Как может быть хуже? - person huggie; 01.09.2012