Как работает новый механизм автоматического подсчета ссылок? - PullRequest
202 голосов
/ 17 июня 2011

Может кто-нибудь кратко объяснить мне, как работает ARC?Я знаю, что он отличается от сборки мусора, но мне просто интересно, как именно он работает.

Кроме того, если ARC делает то, что делает GC, не снижая производительность, то почему Java использует GC?Почему он также не использует ARC?

Ответы [ 6 ]

242 голосов
/ 21 июня 2011

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

С Clang Static Analyzer разработчики LLVMпонял, что эти правила были достаточно надежными, чтобы они могли создать инструмент для выявления утечек и чрезмерных выпусков памяти в путях, которые использует ваш код.

Автоматический логический подсчет ссылок (ARC) является следующим логическимшаг.Если компилятор может распознать, где вы должны хранить и освобождать объекты, почему бы ему не вставить этот код для вас?Жесткие, повторяющиеся задачи - это то, в чем велики компиляторы и их братья.Люди забывают вещи и делают ошибки, но компьютеры гораздо более последовательны.

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

По сравнению с ручным управлением памятью и сборкой мусора, ARC дает вам лучшее из обоих миров, избавляя от необходимости писать код сохранения / освобождения., но не имеет профилей памяти с остановкой и пилообразной памятью, замеченных в среде сбора мусора.Единственным преимуществом сборки мусора по сравнению с этим является его способность справляться с циклами сохранения и тот факт, что присвоение атомарных свойств стоит недорого (как обсуждено здесь ).Я знаю, что заменяю весь свой существующий код Mac GC реализациями ARC.

Что касается того, может ли это быть распространено на другие языки, то оно похоже на систему подсчета ссылок в Objective-C.Может быть трудно применить это к Java или другим языкам, но я не знаю достаточно о деталях низкоуровневого компилятора, чтобы сделать там однозначное утверждение.Учитывая, что именно Apple продвигает эти усилия в LLVM, Objective-C придет первым, если другая сторона не выделит для этого значительных собственных ресурсов.

Обнародование этих шокированных разработчиков на WWDC, так что люди не былиосознавая, что что-то подобное можно сделать.Со временем он может появиться на других платформах, но пока он эксклюзивен для LLVM и Objective-C.

22 голосов
/ 22 ноября 2011

ARC - это просто воспроизведение старого сохранения / освобождения (MRC), а компилятор выясняет, когда вызывать сохранение / освобождение. Она будет иметь более высокую производительность, более низкое пиковое использование памяти и более предсказуемую производительность, чем система GC.

С другой стороны, некоторые типы структуры данных невозможны с ARC (или MRC), в то время как GC может их обрабатывать.

Например, если у вас есть класс с именем node, а node имеет NSArray дочерних элементов и единственную ссылку на его родительский элемент, который «просто работает» с GC. С ARC (и ручным подсчетом ссылок) у вас есть проблема. На любой данный узел будут ссылаться его дочерние элементы, а также родительские элементы.

Как:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

Все в порядке, пока вы используете A (скажем, через локальную переменную).

Когда вы закончите с этим (и B1 / B2 / B3), система GC в конечном итоге решит взглянуть на все, что может найти, начиная со стека и регистров процессора. Он никогда не найдет A, B1, B2, B3, поэтому завершит их и переместит память в другие объекты.

Когда вы используете ARC или MRC и заканчиваете буквой A, у него будет повторный счет 3 (B1, B2, и B3 все ссылаются на него), а у всех B1 / B2 / B3 будет счетчик ссылок 1 (NSArray A удерживает одна ссылка на каждого). Таким образом, все эти объекты остаются живыми, хотя ничто не может их использовать.

Общее решение состоит в том, чтобы решить, что одна из этих ссылок должна быть слабой (не способствовать подсчету ссылок). Это будет работать для некоторых шаблонов использования, например, если вы ссылаетесь на B1 / B2 / B3 только через A. Однако в других шаблонах это дает сбой. Например, если вы иногда держитесь за B1, и ожидаете подняться вверх через родительский указатель и найдете A. Со слабой ссылкой, если вы только держитесь за B1, A может (и обычно будет) испаряться, и принимать B2, и B3 с этим.

Иногда это не проблема, но некоторые очень полезные и естественные способы работы со сложными структурами данных очень сложно использовать с ARC / MRC.

Таким образом, ARC нацеливается на те же проблемы, что и GC. Однако ARC работает с более ограниченным набором шаблонов использования, чем GC, поэтому, если вы взяли язык GC (например, Java) и привили на него что-то вроде ARC, некоторые программы больше не будут работать (или, по крайней мере, будут генерировать тонны заброшенной памяти). и может привести к серьезным проблемам с обменом, исчерпанию памяти или месту подкачки).

Можно также сказать, что ARC придает большее значение производительности (или, возможно, предсказуемости), в то время как GC придает большее значение универсальному решению. В результате GC имеет менее предсказуемые требования к процессору / памяти и более низкую производительность (обычно), чем ARC, но может обрабатывать любые схемы использования. ARC будет работать намного лучше для многих распространенных шаблонов использования, но для нескольких (действительных!) Шаблонов использования он упадет и умрет.

4 голосов
/ 17 июня 2011

Волшебное

Но, более конкретно, ARC работает именно так, как вы делаете с вашим кодом (с некоторыми незначительными отличиями). ARC - это технология времени компиляции, в отличие от GC, которая является средой выполнения и отрицательно скажется на вашей производительности. ARC будет отслеживать ссылки на объекты для вас и синтезировать методы retain / release / autorelease согласно обычным правилам. Из-за этого ARC может также выпускать вещи, как только они больше не нужны, вместо того, чтобы выбрасывать их в пул авто-релиза исключительно для удобства.

Некоторые другие улучшения включают в себя обнуление слабых ссылок, автоматическое копирование блоков в кучу, ускорения по всем направлениям (6x для пулов автоматического выпуска!).

Более подробное обсуждение того, как все это работает, можно найти в Документах LLVM на ARC.

3 голосов
/ 17 июня 2011

Это сильно зависит от сбора мусора.Вы видели предупреждения, которые говорят вам, что у вас могут быть утечки объектов на разных линиях?Эти заявления даже говорят вам, на какой линии вы разместили объект.Это еще один шаг вперед и теперь можно вставлять операторы retain / release в нужных местах, лучше, чем большинство программистов, почти в 100% случаев.Иногда есть некоторые странные случаи сохраняемых объектов, с которыми вам нужно помочь.

0 голосов
/ 03 мая 2019

ARC - это функция компилятора, которая обеспечивает автоматическое управление памятью объектов.

Вместо того, чтобы вам приходилось помнить, когда использовать retain, release и autorelease, ARC оценивает требования времени жизни ваших объектов и автоматическивставляет соответствующие вызовы управления памятью для вас во время компиляции.Компилятор также генерирует соответствующие методы dealloc для вас.

Компилятор вставляет необходимые retain/release вызовы во время компиляции, но эти вызовы выполняются во время выполнения, как и любой другой код.

Следующая диаграмма даст вам лучшее понимание того, как работает ARC.

enter image description here

Те, кто новичок в разработке для iOS и не имеет опыта работы с Objective C. Пожалуйста, обратитесь к документации Apple.для Расширенное руководство по программированию управления памятью для лучшего понимания управления памятью.

0 голосов
/ 31 марта 2017

Очень хорошо объяснено в документации Apple для разработчиков. Читать «Как работает ARC»

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

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

Чтобы узнать Дифф. между сборкой мусора и ARC: прочитайте это

...