Может кто-нибудь кратко объяснить мне, как работает ARC? Я знаю, что это отличается от Сборки мусора, но мне просто интересно, как именно это работает.
Кроме того, если ARC делает то, что делает GC, не снижая производительность, то почему Java использует GC? Почему он не использует ARC?
Ответы:
Каждый новый разработчик, который приходит в 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.
источник
ARC - это просто старое сохранение / освобождение (MRC), а компилятор выясняет, когда вызывать сохранение / освобождение. Он будет иметь более высокую производительность, более низкое пиковое использование памяти и более предсказуемую производительность, чем система GC.
С другой стороны, некоторые типы структуры данных невозможны с ARC (или MRC), в то время как GC может обрабатывать их.
Например, если у вас есть класс с именем node, а node имеет NSArray дочерних элементов и единственная ссылка на его родительский элемент, который «просто работает» с GC. С ARC (и ручным подсчетом ссылок) у вас есть проблема. На любой данный узел будут ссылаться его дочерние элементы, а также родительские элементы.
Подобно:
Все в порядке, пока вы используете 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 будет работать намного лучше для многих распространенных шаблонов использования, но для нескольких (действительных!) Шаблонов использования он упадет и умрет.
источник
foo = nil
.магия
Но, в частности, ARC работает именно так, как вы делаете с вашим кодом (с некоторыми незначительными отличиями). ARC - это технология времени компиляции, в отличие от GC, которая является средой выполнения и отрицательно скажется на вашей производительности. ARC будет отслеживать ссылки на объекты для вас и синтезировать методы retain / release / autorelease согласно обычным правилам. Из-за этого ARC может также выпускать вещи, как только они больше не нужны, вместо того, чтобы выбрасывать их в пул авто-релиза исключительно для удобства.
Некоторые другие улучшения включают обнуление слабых ссылок, автоматическое копирование блоков в кучу, ускорения по всем направлениям (6x для пулов авто-релиза!).
Более подробное обсуждение того, как все это работает, можно найти в Документах LLVM по ARC.
источник
Это сильно зависит от сбора мусора. Вы видели предупреждения, которые говорят вам, что у вас могут быть утечки объектов на разных линиях? Эти заявления даже говорят вам, на какой линии вы разместили объект. Это был шаг вперед и теперь можно вставлять операторы
retain
/release
в правильные места, лучше, чем большинство программистов, почти в 100% случаев. Иногда есть некоторые странные случаи сохраняемых объектов, с которыми вам нужно помочь.источник
Очень хорошо объяснено разработчиком документации Apple. Читать "Как работает ARC"
Чтобы узнать Diff. между сборкой мусора и ARC: прочитайте это
источник
ARC - это функция компилятора, которая обеспечивает автоматическое управление памятью объектов.
Вместо того, чтобы вы помнили, когда использовать
retain, release
, иautorelease
ARC оценивает требования к сроку службы ваших объектов и автоматически вставляет соответствующие вызовы управления памятью для вас во время компиляции. Компилятор также генерирует подходящие методы dealloc для вас.Компилятор вставляет необходимые
retain/release
вызовы во время компиляции, но эти вызовы выполняются во время выполнения, как и любой другой код.Следующая диаграмма даст вам лучшее понимание того, как работает ARC.
Те, кто новичок в разработке для iOS и не имеют опыта работы с Objective C. Пожалуйста, обратитесь к документации Apple для Руководства по программированию Advanced Memory Management для лучшего понимания управления памятью.
источник