В ARC или не в ARC? Каковы плюсы и минусы? [закрыто]

113

Я еще не использовал ARC, поскольку большая часть кода в проекте, над которым я сейчас работаю, была написана до iOS 5.0.

Мне просто интересно, перевешивает ли удобство отказа от сохранения / выпуска вручную (и, вероятно, более надежного кода, который в результате появляется?) Любую «стоимость» использования ARC? Каков ваш опыт использования ARC и вы бы порекомендовали его?

Так:

  • Какую пользу ARC может принести проекту?
  • Есть ли у ARC такая же стоимость, как сборка мусора в Java?
  • Вы использовали ARC, и если да, то как вы его нашли?
Саймон Витингтон
источник
На ipad / ios нет сборщика мусора. Вы про OS X?
dasblinkenlight 06
1
Приношу свои извинения, я неуместно использую термины Java. Я имею в виду, что с помощью ARC объекты могут храниться в памяти дольше, чем необходимо, а затем через некоторое время освобождены как группа в пуле с автоматическим выпуском. Это эффект их сохранения и последующего выпуска вместе с другими объектами, аналогично сборке мусора в Java, о которой я говорю.
Саймон Витингтон,
3
@TenementFunster, для того же кода (за вычетом вызовов для освобождения) ARC будет удерживать объект не дольше, чем код, отличный от ARC. Фактически, он часто выпускает его раньше, чем вы. Есть небольшое количество вещей, которые несколько медленнее, но они настолько ускорили общие шаблоны, что это затмевает влияние на производительность. Для многих распространенных шаблонов (например, с сохранением объекта, который был возвращен с автозапуском) вы буквально не можете написать его вручную так быстро, как ARC сделает это автоматически.
Роб Напье
1
Что касается сборки мусора, см. Мой ответ на этот аналогичный вопрос: в чем разница между автоматическим подсчетом ссылок Objective-C и сборкой мусора?
Брэд Ларсон

Ответы:

147

Обратной стороны нет. Используй это. Сделай это сегодня. Это быстрее, чем ваш старый код. Это безопаснее, чем ваш старый код. Это проще, чем ваш старый код. Это не сборщик мусора. У него нет накладных расходов времени выполнения GC. Компилятор вставляет удержания и освобождает все места, которые у вас должны быть. Но он умнее вас и может оптимизировать те, которые на самом деле не нужны (точно так же, как он может разворачивать циклы, удалять временные переменные, встроенные функции и т. Д.)

Хорошо, теперь я расскажу о небольших минусах:

  • Если вы давно являетесь разработчиком ObjC, вы будете дергаться около недели, когда увидите код ARC. Вы очень быстро с этим справитесь.

  • При переходе к коду Core Foundation возникают некоторые (очень) небольшие сложности. Есть немного больше сложностей в работе со всем, что рассматривает idкак void*. idДля правильного выполнения таких вещей, как C-массивы, нужно немного подумать. Причудливое обращение с ObjC va_argsтакже может вызвать проблемы. Большинство задач, связанных с математикой для указателя ObjC, сложнее. В любом случае у вас не должно быть много этого.

  • Вы не можете поместить idв struct. Это довольно редко, но иногда используется для упаковки данных.

  • Если вы не следовали правильному именованию KVC, и вы смешиваете код ARC и не-ARC, у вас будут проблемы с памятью. ARC использует именование KVC для принятия решений об управлении памятью. Если это весь код ARC, то это не имеет значения, потому что он будет делать то же самое «неправильно» с обеих сторон. Но если это смешанный ARC / non-ARC, тогда есть несоответствие.

  • ARC будет вызывать утечку памяти во время генерирования исключения ObjC. Исключение ObjC должно быть очень близко по времени к завершению вашей программы. Если вы обнаруживаете значительное количество исключений ObjC, вы используете их неправильно. Это можно исправить с помощью -fobjc-arc-exceptions, но это влечет за собой штрафы, описанные ниже:

  • ARC не будет утечки памяти во время генерирования исключений ObjC или C ++ в коде ObjC ++, но это происходит за счет производительности как времени, так и пространства. Это еще одна из длинного списка причин минимизировать использование ObjC ++.

  • ARC вообще не будет работать на iPhoneOS 3 или Mac OS X 10.5 или более ранней версии. (Это не позволяет мне использовать ARC во многих проектах.)

  • __weakуказатели не работают правильно в iOS 4 или Mac OS X 10.6, что очень жаль, но их довольно легко обойти. __weakуказатели - это здорово, но они не главное преимущество ARC.

Для более 95% кода ARC великолепен, и нет никаких причин избегать его (при условии, что вы можете справиться с ограничениями версии ОС). Для кода, отличного от ARC, вы можете передавать -fno-objc-arcего пофайлово. К сожалению, Xcode делает это намного труднее, чем должно быть на практике. Вам, вероятно, следует переместить код, не являющийся ARC, в отдельный xcodeproj, чтобы упростить это.

В заключение, как можно скорее переключитесь на ARC и никогда не оглядывайтесь назад.


РЕДАКТИРОВАТЬ

Я видел пару комментариев вроде «использование ARC не заменяет знание правил управления памятью Какао». В основном это правда, но важно понимать, почему и почему нет. Во-первых, если весь ваш код использует ARC, и вы нарушаете Три волшебных словаповсюду, у вас все равно не будет проблем. Это шокирует, но вот и все. ARC может сохранить некоторые вещи, которые вы не хотели сохранять, но также освободит их, так что это не имеет значения. Если бы я преподавал сегодня новый класс в Какао, я бы, вероятно, потратил не более пяти минут на фактические правила управления памятью и, вероятно, упомянул бы только правила именования управления памятью при обсуждении именования KVC. Я считаю, что с ARC вы действительно можете стать приличным начинающим программистом, вообще не изучая правил управления памятью.

Но вы не смогли бы стать достойным программистом среднего уровня. Вам необходимо знать правила, чтобы правильно соединиться с Core Foundation, и каждый промежуточный программист должен иметь дело с CF в какой-то момент. И вам нужно знать правила для кода смешанного ARC / MRC. И вам нужно знать правила, когда вы начинаете возиться с void*указателями на id(которые вам по-прежнему нужны для правильного выполнения KVO). А блоки ... ну, управление блочной памятью - это просто странно.

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

Роб Напье
источник
3
Одна вещь, о которой нужно быть очень осторожной (в том числе и в не-ARC, но в большей степени в ARC, потому что теперь это так невидимо), - это циклы сохранения. Мой совет: 1) если вы обнаружите, что храните блок objc в качестве переменной экземпляра, внимательно посмотрите на него, чтобы увидеть, может ли он захватить объект, к которому он принадлежит, даже косвенно. 2) Собственно спроектируйте свой объектный граф, а не просто позволяйте этому случиться. Вы должны знать, кто чем владеет, если вы хотите писать хороший код. 3) Используйте heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man 06
1
@Catfish_Man Все хорошие моменты. Удерживать петли всегда было проблемой. Новый совет Apple в точности такой, как вы говорите в пункте 2. Нам нужно думать о графах объектов, а не сохранять и выпускать. №1 - это серьезная проблема с блоками, и одна из нескольких причин, по которым я считаю, что блоки - это смешанное благо, к которому следует подходить с осторожностью.
Роб Нэпир,
2
Есть один серьезный недостаток, о котором не упоминалось: перекрестная совместимость. Для нас, смелых и глупых душ, которые сталкиваются с пустошами, известными как кроссплатформенное программирование, ARC просто не вариант, по крайней мере, до тех пор, пока GNU снова не расширит свои функции времени выполнения и компилятора ObjC (они говорят, что еще больше).
Rabbit
2
Вы можете использовать ARC, за исключением того, что вам необходимо поддерживать устройства iOS 3.x. Кстати, обязательно используйте Xcode для перехода (Edit> Refactor> Convert to Objective-C ARC). Во время этого процесса Xcode будет выполнять много проверок, чтобы убедиться, что ваш код работает, и выяснять все коды, которые нарушают эти правила проектирования.
ZhangChn
1
Отлично .. ответьте точечно. это сотый от меня. Поздравляю на столетие;)
Аджай Шарма
20

Будет получено больше технических ответов, чем у меня, но вот что:

  • ARC! = Сборка мусора. Штраф за время выполнения отсутствует, это делается во время компиляции.
  • ARC также! = Просто автоматическое освобождение всего, как вы предлагаете в своем комментарии. Читать документы
  • Это потрясающе , когда вы понимаете , как много ручного управления ссылочного вы были делать
  • Используй это!
  • Один недостаток - поддержка старого, не дугового кода внезапно становится очень утомительной.
jrturton
источник
Да, именно поэтому я его до сих пор не использовал - я не уверен, что смогу пройти через наш значительный объем уже существующего кода, чтобы преобразовать его ... Я обязательно попробую его в следующем проекте. Спасибо за ответ :)
Саймон Витингтон
Дело не в том, что поддерживать старый код становится сложнее, дело в том, что изменились ваши ожидания. Так что несправедливо обвинять ARC в облегчении жизни. Xcode позволяет легко преобразовать ваш старый код в ARC, когда вы будете готовы, но вы, очевидно, не сможете его использовать, если вам все еще нужно поддерживать более старые версии iOS.
Калеб
1
@Caleb Я не обвинял ARC, просто это единственный недостаток, который я видел до сих пор - он испортил меня насквозь за время одного проекта.
jrturton 06
Да; Я не перечислял это как проблему, но есть небольшая проблема выхода из практики управления памятью, когда вам нужно переключаться между базами кода. Некоторые из моих проектов работают на 10.4, поэтому я все еще много работаю над Objective-C 1.0 (так что никаких @synthesize, не говоря уже о ARC). Но к переключению режимов привыкаешь довольно хорошо.
Роб Нэпир,
@jrturton Я должен был прояснить, что написал это для пользы OP и будущих читателей, которые не могут понять, что делает ARC. Я точно знаю, что вы имеете в виду, просто не хотел, чтобы кто-то сделал ошибочный вывод, что смешивание кода ARC и не-ARC создает проблему.
Калеб
16

Какую пользу ARC может принести проекту?

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

Сколько на самом деле «стоит» сборка мусора?

В iOS нет сборки мусора. ARC похож на GC в том, что вам не нужно вручную сохранять или освобождать объекты. В отличие от GC, здесь нет сборщика мусора. Модель сохранения / освобождения по-прежнему применяется, просто компилятор вставляет соответствующие вызовы управления памятью в ваш код во время компиляции.

Вы использовали ARC, и если да, то как вы его нашли?

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

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

Калеб
источник
1
Я имел в виду лучший ответ!
jrturton 06
1
Да, отличный ответ. Итак, действительно ли в ARC нет недостатка, кроме необходимости научиться доверять тому, что он работает? В таком случае это кажется слишком хорошим, чтобы быть правдой?
Саймон Витингтон,
4

Я думаю, что ARC - отличная идея. По сравнению с GC, вы можете съесть свой торт и съесть его. Я склонен полагать, что MRC устанавливает бесценную «дисциплину» в отношении управления памятью, от которой выиграет каждый. Но я также согласен с тем, что настоящая проблема, о которой нужно знать, - это владение объектами и графы объектов (как многие указывали), а не низкоуровневые подсчеты ссылок как таковые.

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

Тем не менее, я лично своего рода ремесленник и еще не совершил переход. Я только начал использовать Git ...

ОБНОВЛЕНИЕ: Итак, я перенес всю свою игру, включая библиотеку gl, и пока никаких проблем (за исключением помощника по миграции в Xcode 4.2). Если вы начинаете новый проект, дерзайте.

Николас Миари
источник
2

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

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

Иоахим Исакссон
источник
2

Единственный недостаток, с которым я столкнулся, - это использование библиотеки с множеством функций и данных CoreFoundation. В MRC вам не нужно было беспокоиться об использовании CFStringRefвместо NSString*. В ARC вы должны указать, как они взаимодействуют (базовый мост? Освободить объект CoreFoundation и переместить его в ARC? Сделать объект Какао как сохраненный объект +1 CoreFoundation?) Кроме того, в OS X он доступен только в 64- битовый код (хотя у меня есть заголовок, который позволяет обойти это…).

MaddTheSane
источник