Что такое сборщик мусора c
Перейти к содержимому

Что такое сборщик мусора c

  • автор:

Сборка мусора

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

Заголовок Описание
Основы сборки мусора Описание работы сборки мусора, выделения объектов в управляемой куче и других базовых понятий.
Сборка мусора рабочей станции и сборка мусора сервера Описывает различия между сборкой мусора рабочей станции для клиентских приложений и сборкой мусора сервера для серверных приложений.
Фоновая сборка мусора Описывает фоновую сборку мусора, которая представляет собой сборку объектов поколения 0 и 1 во время сборки объектов поколения 2.
Куча больших объектов Описывает кучу больших объектов (LOH) и то, как для них выполняется сборка мусора.
Сборка мусора и производительность Проверки производительности, которые можно использовать для диагностики проблем со сборкой мусора и производительностью.
Индуцированные коллекции Описание выполнения сборки мусора.
Режимы задержки Описание режимов, которые определяют степень вмешательства сборщика мусора.
Оптимизация совместного размещения веб-сайтов Способы оптимизации сборки мусора на серверах, совместно используемыми небольшими веб-узлами.
Уведомления о сборке мусора Определение необходимости полной сборки мусора и времени завершения этой операции.
Отслеживание ресурсов домена приложения Способы наблюдения за использованием ЦП и памяти доменом приложения.
Слабые ссылки Описание функциональных возможностей, которые позволяют сборщику мусора обрабатывать объект, разрешая при этом приложению получать доступ к этому объекту.

Справочник

  • System.GC
  • System.GCCollectionMode
  • System.GCNotificationStatus
  • System.Runtime.GCLatencyMode
  • System.Runtime.GCSettings
  • GCSettings.LargeObjectHeapCompactionMode
  • Object.Finalize
  • System.IDisposable

См. также

Обратная связь

Были ли сведения на этой странице полезными?

Сборка мусора, управление памятью и указатели

Ранее в теме Типы значений и ссылочные типы мы рассматривали отдельные типы данных и как они располагаются в памяти. Так, при использовании переменных типов значений в методе, все значения этих переменных попадают в стек. После завершения работы метода стек очищается.

При использовании же ссылочных типов, например, объектов классов, для них также будет отводиться место в стеке, только там будет храниться не значение, а адрес на участок памяти в хипе или куче, в котором и будут находиться сами значения данного объекта. И если объект класса перестает использоваться, то при очистке стека ссылка на участок памяти также очищается, однако это не приводит к немедленной очистке самого участка памяти в куче. Впоследствии сборщик мусора (garbage collector) увидит, что на данный участок памяти больше нет ссылок, и очистит его.

Test(); void Test() < Person tom = new Person("Tom"); Console.WriteLine(tom.Name); >record class Person(string Name);

В методе Test создается объект Person. С помощью оператора new в куче для хранения объекта CLR выделяет участок памяти. А в стек добавляет адрес на этот участок памяти. В неявно определенном методе Main мы вызываем метод Test. И после того, как Test отработает, место в стеке очищается, а сборщик мусора очищает ранее выделенный под хранение объекта Person участок памяти.

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

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

Так же надо отметить, что для крупных объектов существует своя куча — Large Object Heap . В эту кучу помещаются объекты, размер которых больше 85 000 байт. Особенность этой кучи состоит в том, что при сборке мусора сжатие памяти не проводится по причине больших издержек, связанных с размером объектов.

Несмотря на то что, на сжатие занятого пространства требуется время, да и приложение не сможет продолжать работу, пока не отработает сборщик мусора, однако благодаря подобному подходу также происходит оптимизация приложения. Теперь чтобы найти свободное место в куче среде CLR не надо искать островки пустого пространства среди занятых блоков. Ей достаточно обратиться к указателю кучи, который указывает на свободный участок памяти, что уменьшает количество обращений к памяти.

Кроме того, чтобы снизить издержки от работы сборщика мусора, все объекты в куче разделяются по поколениям. Всего существует три поколения объектов: 0, 1 и 2-е.

К поколению 0 относятся новые объекты, которые еще ни разу не подвергались сборке мусора. К поколению 1 относятся объекты, которые пережили одну сборку, а к поколению 2 — объекты, прошедшие более одной сборки мусора.

Когда сборщик мусора приступает к работе, он сначала анализирует объекты из поколения 0. Те объекты, которые остаются актуальными после очистки, повышаются до поколения 1.

Если после обработки объектов поколения 0 все еще необходима дополнительная память, то сборщик мусора приступает к объектам из поколения 1. Те объекты, на которые уже нет ссылок, уничтожаются, а те, которые по-прежнему актуальны, повышаются до поколения 2.

Поскольку объекты из поколения 0 являются более молодыми и нередко находятся в адресном пространстве памяти рядом друг с другом, то их удаление проходит с наименьшими издержками.

Класс System.GC

Функционал сборщика мусора в библиотеке классов .NET представляет класс System.GC . Через статические методы данный класс позволяет обращаться к сборщику мусора. Как правило, надобность в применении этого класса отсутствует. Наиболее распространенным случаем его использования является сборка мусора при работе с неуправляемыми ресурсами, при интенсивном выделении больших объемов памяти, при которых необходимо такое же быстрое их освобождение.

Рассмотрим некоторые методы и свойства класса System.GC:

  • Метод AddMemoryPressure информирует среду CLR о выделении большого объема неуправляемой памяти, которую надо учесть при планировании сборки мусора. В связке с этим методом используется метод RemoveMemoryPressure , который указывает CLR, что ранее выделенная память освобождена, и ее не надо учитывать при сборке мусора.
  • Метод Collect приводит в действие механизм сборки мусора. Перегруженные версии метода позволяют указать поколение объектов, вплоть до которого надо произвести сборку мусора
  • Метод GetGeneration(Object) позволяет определить номер поколения, к которому относится переданый в качестве параметра объект
  • Метод GetTotalMemory возвращает объем памяти в байтах, которое занято в управляемой куче
  • Метод WaitForPendingFinalizers приостанавливает работу текущего потока до освобождения всех объектов, для которых производится сборка мусора

Работать с методами System.GC несложно:

// . long totalMemory = GC.GetTotalMemory(false); GC.Collect(); GC.WaitForPendingFinalizers(); //.

С помощью перегруженных версий метода GC.Collect можно выполнить более точную настройку сборки мусора. Так, его перегруженная версия принимает в качестве параметра число — номер поколения, вплоть до которого надо выполнить очистку. Например, GC.Collect(0) — удаляются только объекты поколения 0.

Еще одна перегруженная версия принимает еще и второй параметр — перечисление GCCollectionMode . Это перечисление может принимать три значения:

  • Default : значение по умолчанию для данного перечисления (Forced)
  • Forced : вызывает немедленное выполнение сборки мусора
  • Optimized : позволяет сборщику мусора определить, является ли текущий момент оптимальным для сборки мусора

Например, немедленная сборка мусора вплоть до первого поколения объектов: GC.Collect(1, GCCollectionMode.Forced);

Автоматическая сборка мусора в программах на С++ [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.

Закрыт 7 лет назад .

  • http://www.cantrip.org/wave12.html
  • http://www.cs.wustl.edu/~schmidt/PDF/C++-mem-mgnt4.pdf

Отслеживать
Dmitry Ponyatov
задан 15 дек 2016 в 12:40
Dmitry Ponyatov Dmitry Ponyatov
828 6 6 серебряных знаков 14 14 бронзовых знаков
Чисто не там где убирают, а там где не сорют.
15 дек 2016 в 12:48

Сборщик мусора — насколько я понимаю — библиотека. это в с# сборщик интегрирован, а у с++ штатного нету. И с++11 штатного так же нету. Вот какие функции есть у вашей мусорной библиотеки — такими и располагаете.

15 дек 2016 в 12:49
@nick_n_a, а как же shared_ptr и компания?
15 дек 2016 в 12:51
Их очень мало и они умещаются в одну страницу. Пока, GC для C++ в стандарте нет.
15 дек 2016 в 13:28

@Dmitry Ponyatov Нет никаких средств в C++ для упрощения создания GC. Проблема состоит в том, что нужно менять сам язык, так как необходимо будет менять идеологию работы с ресурсами в клиентском коде. Поэтому если вам так нужен GC, то имейте дело с C++/CLI.

15 дек 2016 в 13:59

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

В C++ нет и не может быть средств сборки мусора. Вместо этого можно использовать умные указатели. Наиболее универсальный из них — shared_ptr . В конструктор умного указателя нужно передать указатель на уже выделенную память, и больше нигде этот указатель использовать нельзя. При копировании объекта shared_ptr , при передаче его как параметр функции увеличивается внутренний счётчик объектов, имеющих в себе один и тот же указатель. Как только последний объект shared_ptr уничтожается (выходит из области видимости), автоматически освобождается память, на которую ссылается внутренний указатель shared_ptr . Вот пример использования.

void foo() < //Создаём умный указатель, передав ему обычный указатель на массив из 10 целых чисел std::shared_ptrx(new int(10)); //Вызываем функцию, которая использует этот указатель. На стеке создаётся копия объекта x, которая указывает на ту же память bar(x); //Заканчивается область видимости, удаляется x, освобождается память по данному указателю > void bar(std::shared_ptr y) < //Функция работает со своей копией объекта y[5] = 10; //Область видимости закочилась, объект y удаляется, но так как есть ещё один такой же умный указатель, память не освобождается >

Отслеживать
ответ дан 15 дек 2016 в 16:42
4,725 4 4 золотых знака 28 28 серебряных знаков 53 53 бронзовых знака

Стоит добавить, что shared_ptr имеет недостаток: кольцевые ссылки требуют ручного разрыва цикла (что вынуждает всё равно заботиться о точном моменте уничтожения структуры данных).

15 дек 2016 в 17:20
@VladD, weak_ptr
15 дек 2016 в 18:47
@yrHeTaTeJlb weak_ptr умеет находить и разрывать кольцевые ссылки?
15 дек 2016 в 19:39

@yrHeTaTeJlb: Ну, во-первых, этого нет в ответе, а во-вторых, добавляется задача правильной расстановки типов указателей, чтобы нужная структура данных случайно не оказалось без сильных ссылок. Это вполне может оказаться нетривиально для нетривиальных отношений между объектами (то есть, там где нету самоочевидного дерева).

Что такое сборщик мусора в программировании

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

Ситуация

Когда мы пишем программы, мы обычно действуем по такому принципу:

  • если надо — объявляем переменную и храним в ней данные;
  • если переменных нужно много — делаем много переменных;
  • переменные можно объявлять внутри циклов, а циклы вкладывать в другие циклы;

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

Проблема

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

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

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

Решение — очистка мусора и управление памятью

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

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

Автоматический режим называется сборкой мусора. Это такая отдельная мини-программа внутри основной программы, которая периодически пробегает по объектам и переменным в коде и смотрит, нужны они или нет. Если нет — сборщик мусора сам удаляет переменную и освобождает память.

Особенности ручного управления

При ручной работе с памятью программист получает полный контроль над ресурсами и может в любой момент освободить уже ненужную память. Это значит, что можно написать такую программу, когда в сумме переменным нужно 500 мегабайт памяти, но за счёт своевременного удаления всегда заняты только 100 мегабайт.

Ручное управление идеально для систем со слабыми ресурсами и систем реального времени — там, где программа не имеет права тормозить.

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

Особенности автоматического сборщика

Автоматический сборщик сам ходит по программе во время исполнения и аккуратно подчищает память, как только находит мусор.

Вроде хорошо, но нет. Сборщик мусора тоже работает неидеально:

❌ Сборщик удаляет только те переменные, в которых он уверен стопроцентно. Если есть один шанс, что переменная может когда-нибудь понадобиться, — её оставляют в памяти. То есть эффективность не стопроцентная.

❌ Сборщик — это отдельная программа, которая работает вместе с основной. И ей тоже нужны ресурсы и процессорное время. Это замедляет работу основной программы. Как если бы уборщик приходил в отделение Сбербанка посреди рабочего дня и заставлял всех на два часа покинуть рабочие места, чтобы он тут провёл влажную уборку.

❌ Если рабочей памяти очень мало, то сборщик будет работать постоянно. Но ему тоже нужна своя память для работы. И может получиться, что сборщик, например, занимает 100 МБ, а освобождает 10 МБ. Может оказаться так, что без сборщика программа будет работать эффективнее.

Автоматические сборщики — добро или зло?

Тут у разработчиков мнения разделяются.

С точки зрения быстродействия сборщики — однозначно зло, потому что они всегда замедляют работу. Есть ситуации, когда замедление незаметно, а бывает, когда оно критично.

  • Например, если офисное приложение иногда подвисает на полсекунды, это почти никто не замечает. Возможно, оно у вас подвисает прямо сейчас.
  • А если на полсекунды подвиснет контроллер ракетного двигателя, то эта ракета полетит не в космос, а в Вашингтон. Хьюстон, у нас проблема.

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

Что выбрать?

С выбором интересная ситуация.

Если вы пишете приложения для iOS или OSX, вам нельзя использовать сборщики мусора из соображений быстродействия.

Языки типа JavaScript и Ruby собирают мусор сами, вы об этом можете даже никогда не узнать.

В некоторые языки можно подключить сбор мусора, пожертвовав производительностью — например, в Java, C или C++.

Путь самурая — вручную управлять памятью и делать суперпроизводительные приложения, которые летают даже на процессоре от карманного калькулятора. Но жизнь сложна и разнообразна, и однажды за всеми нами тоже придут наши собственные… сборщики.

Веб-разработка — это новый чёрный

На базе веб-технологий делают всё — от сложного софта до высокобюджетных игр. Изучите технологии и начните карьеру в ИТ. Старт бесплатно. Попробуйте, вдруг вам понравится.

Получите ИТ-профессию

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *