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

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

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

ARC против сборки мусора (GC)

Многие языки программирования используют сборку мусора для сбора неиспользуемой памяти, тогда как swift использует ARC.

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

Сборка мусора - это фоновый процесс, который выполняется в неопределенное время в течение жизненного цикла приложения (обычно во время простоя) в два этапа. На шаге 1 помечаются все объекты, которые считаются «безопасными для сбора», а на шаге 2 эти объекты освобождаются и помечаются для сбора.

ARC запускает часть кода приложения, поэтому он очень детерминирован. Объекты освобождаются, как только они не требуются. Однако, в отличие от GC, ARC не может обнаруживать эталонные циклы. Следовательно, ARC требует от разработчиков понимания взаимосвязи между ссылочными объектами в системе и предотвращения создания циклов владения / ссылки.

Избегайте ссылочных циклов

Главное, что нужно сделать разработчику, - это не допустить циклических циклов владения. Когда мы ссылаемся на объект, на ум приходит реализация по умолчанию - сильная ссылка. Чтобы отслеживать циклы сохранения, нам нужно следить за отношениями родитель-потомок и следить за тем, чтобы дочерний элемент не ссылался на родительский СИЛЬНО, а вместо этого был помечен как отношения, не связанные с владением. т.е. либо слабые, либо бездомные.

Справочные циклы

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

У нас есть класс Employee:

Мы видим, что при инициализации Employee мы печатаем сообщение Employee (employee name) initialised 🥳, а когда тот же сотрудник деинициализируется, мы печатаем Employee (name) de-initialised 💀, чтобы мы могли наблюдать время жизни объектов Employee.

Давайте создадим подкласс класса Employee, чтобы создать класс Manager и класс Worker, как показано ниже:

Когда у нас есть оба этих класса, мы создаем один объект Manager manager, три объекта Worker - employee1, employee2, employee3, а затем назначаем соответствующие свойства менеджера и отчетов, как показано во фрагменте кода.

Оператор do создает область видимости, и область действия завершается после завершения выполнения оператора do.

Можете ли вы предсказать, что будет напечатано, если мы запустим нашу игровую площадку сейчас?

Цикл сохранения

В результате выполнения на нашей консоли Xcode будет напечатано следующее:

Мы видим, что все четыре объекта инициализированы должным образом, но ни один из них не был деинициализирован, даже когда мы вышли за пределы области видимости. Почему это было?

Чтобы ответить на этот вопрос, давайте посмотрим на график памяти для этих четырех объектов, которые были инициализированы в области видимости:

Как видите, manager имеет сильную ссылку на свой employees, а в ответ каждый сотрудник имеет сильную ссылку на manager. Следовательно, когда manager выходит за пределы области видимости, его счетчик ссылок равен 3, поэтому его нельзя деинициализировать. Точно так же каждый employee имеет счетчик ссылок 1, поэтому ни один из них не будет деинициализирован, и у нас есть утечка памяти.

«Слабый» спешит на помощь

Мы можем решить эту проблему, пометив отношение менеджера в классах Worker как weak .

Слабый всегда используется для переменной или свойства var и всегда используется для необязательного.

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

Давайте исправим код в приведенном выше примере.

Все, что нам нужно было сделать, это добавить ключевое слово weak к необязательному свойству manager в классе Worker.

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

Имейте в виду, что если вы установите какие-либо наблюдатели свойств для слабых свойств, они не будут вызываться, когда ARC установит для этой ссылки значение nil.

Цикл сохранения прерван

Результат выполнения теперь будет напечатан на нашей консоли Xcode:

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

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

За другими обновлениями вы можете следить за мной в Твиттере на моем твиттере @NavRudraSambyal

Спасибо за чтение, поделитесь, если вы сочли полезным :)

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

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

Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее и лучше строить лучшие модели машинного обучения.