Что такое сборка мусора и как она влияет на производительность вашей программы? — CloudSavvy ИТ

Shutterstock / Smit

Сборка мусора — это функция многих языков, таких как C # и Java. Хотя ручное управление памятью, такое как C ++, может быть довольно быстрым, автоматическая сборка мусора улучшает качество жизни разработчиков. Однако важно понимать последствия для производительности, если оставить GC делать свою работу.

Стек против кучи

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

В Куча работает быстро и используется для типов значений с фиксированным размером байта. Это, конечно же, та же физическая память, что и куча, просто она быстрая, потому что это очень упорядоченная структура данных First-In, Last-Out. Всякий раз, когда вы создаете локальную переменную, она сохраняет ее в стеке, и всякий раз, когда ваша функция завершается и переменная выходит за пределы области видимости, она автоматически удаляется из стека.

Это очень быстрый процесс, который делает выделение стека практически бесплатным. Хотя есть снижение производительности, это настолько дешево, насколько это возможно.

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

Выделение кучи также медленнее, чем выделение стека.

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

Очистка вашего мусора

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

В языках ручного управления памятью, таких как C ++, память обрабатывается, ну, вручную. Вы должны вручную освободить память и удалить объекты, которые больше не используете, используя ссылку или указатель на ячейку памяти этого объекта. Хотя это может быть очень быстро, кодировать это неинтересно и может привести к ошибкам памяти и уязвимостям. Это одна из основных причин, по которой C ++ считается «сложным» языком программирования для изучения и программирования.

Альтернативой ручному управлению является автоматическая работа машины. Это то, что называется сборкой мусора.

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

Например, возьмем следующий псевдокод, который создает и «удаляет» объект.

object refToObject = new object();
refToObject = null;

С refToObject больше не ссылается на new object() который был создан, сборщик мусора увидит, что новый объект болтается без ссылки на него из любого места, и удалит его всякий раз, когда он соберет мусор в следующий раз.

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

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

  • Когда в системе мало памяти.
  • Процент памяти в куче превышает определенный порог. Этот порог регулируется автоматически, и в основном это происходит всякий раз, когда GC обнаруживает, что ваша программа нуждается в очистке.
  • Когда он запускается вручную, например, с GC.Collect().

Влияние на производительность

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

Подумайте об этом так: ваш процессор может работать только над одним делом за раз. С C ++ он всегда работает с вашим кодом, включая биты, удаляющие память. С GC ваша программа не удаляет память и работает до тех пор, пока не создаст мусор. Затем он приостанавливается, и ЦП переключается на работу по сборке мусора. Если это происходит часто, это может снизить производительность приложения.

Обычно это довольно быстро, обычно не более пары миллисекунд. Для .NET это зависит от того, какая память очищается, поскольку она отслеживает память в разных «поколениях»:

  • Поколение 0, самое молодое поколение, которое содержит недолговечные объекты, такие как временные переменные.
  • Поколение 1, который действует как буфер между краткосрочными и долгосрочными объектами. Если объект выживает после попытки сборки мусора, он будет «повышен» до более высокого поколения.
  • Поколение 2, последний, который отслеживает долгосрочные объекты.

GC будет проверять объекты в Gen0, затем Gen1, затем Gen2. Поскольку они содержат только временные или вновь созданные объекты, очистка Gen0 и Gen1 обычно выполняется довольно быстро, но Gen2 содержит много памяти. Выполнение «полной сборки мусора» может быть намного медленнее, чем сборка эфемерного мусора.

Как повысить производительность?

Итак, что вы можете сделать, чтобы предотвратить это? Что ж, в конце концов, ваш мусор нужно вывозить. Единственное, что вы можете сделать, это уменьшить количество мусора, который ваша программа выбрасывает.

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

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

Этот код будет запущен 10 000 раз и оставит 10 000 бесхозных списков, выделенных в памяти, в конце функции.Запустите новый список перед циклом, чтобы выполнить первое выделение, затем запустите .Clear или сбросьте данные, чтобы сэкономить место в памяти и создать мусор.

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

Похожие записи

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

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