Когда НЕ использовать сборку мусора? - PullRequest
12 голосов
/ 10 марта 2009

Очевидные случаи, когда вы не используете сборщик мусора, это жесткая работа в реальном времени, строго ограниченная память и желание немного поиграться с указателями. Есть ли другие, менее обсуждаемые, веские причины, по которым кто-то предпочел бы ручное управление памятью вместо GC?

Ответы [ 11 ]

5 голосов
/ 10 марта 2009

МОЖНО использовать сборщик мусора в режиме реального времени, если у вас есть полностью инкрементный сборщик мусора с ограниченным временем выполнения на байт выделенной памяти, поэтому, как ни странно, это НЕ обязательно причина не использовать сборщик мусора :)

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

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

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

Наконец, сборка мусора, конечно же, потребляет процессорное время :) Так что, если вы можете кодировать управление памятью вручную, вы можете сохранить циклы процессора, которые бы использовал сборщик мусора:)

3 голосов
/ 10 марта 2009

Временное безумие?

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

В наши дни есть программный анализ, который позволит компилятору сделать это за вас, но если вы пишете код на C, вы делаете это вручную. Есть реализация с примерами в C Дейве Хэнсоне Интерфейсы и Реализации , и она используется в компиляторе lcc Фрейзера и Хансона , который написан на C без сборщика мусора.

2 голосов
/ 10 марта 2009

Единственная причина НЕ использовать сборщик мусора для управления ресурсами - это если вы хотите использовать RAII ala C ++, но поскольку он применяется исключительно к памяти, даже тогда разумно использовать его. (Примечание: это все еще возможно, с учетом причин недетерминированной финализации).

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

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

В конечном итоге это сводится к компромиссу - чем более специализированы ваши требования, особенно в том, что касается поточно-ориентированного RAII, тем сложнее реализовать GC, и GC может не купить вас слишком дорого для вашего приложения.

2 голосов
/ 10 марта 2009

При программировании для встроенных устройств с ограниченными ресурсами. Например, iPhone использует подсчет ссылок.

Или при программировании чего-то очень интенсивного на вашем компьютере. SETI @ Home и видеоигры приходят на ум.

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

1 голос
/ 11 декабря 2011

Есть ли другие, менее обсуждаемые, веские причины, по которым кто-то предпочел бы ручное управление памятью вместо GC?

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

Например, следующая программа F # создает массив из 10 000 точек и затем обменивается ими:

do
  let xs = Array.init 10000 int
  let timer = System.Diagnostics.Stopwatch.StartNew()
  for i=0 to xs.Length-2 do
    for j=i+1 to xs.Length-1 do
      let t = xs.[i]
      xs.[i] <- xs.[j]
      xs.[j] <- t
  printfn "%f" timer.Elapsed.TotalSeconds

Измените это int на string, и программа будет работать в 2 раза медленнее, потому что целые могут быть обменены напрямую, тогда как обмен ссылочными типами должен иметь два барьера записи.

Еще одна важная ситуация, которую люди любят чистить под ковром, - это патологическое поведение обычных ГК. Сегодня большинство сборщиков мусора являются поколениями, что означает, что они нанимаются в питомник, а затем эвакуируют оставшихся в живых старшему поколению (как правило, разметку). Это хорошо работает, когда гипотеза поколения (что объекты умирают, молодые и старые объекты редко ссылаются на более новые объекты) справедлива, потому что большинство объектов в детской комнате мертвы, когда она эффективно очищается. Но объекты не всегда умирают молодыми, а старые объекты иногда полны указателей на новые объекты.

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

FWIW, я полагаю, что GC региона марки могут избежать этих проблем в будущем. В ГК «Марк-регион» старое поколение - это коллекция бывших питомников. Когда локальная область потока заполняется и обнаруживается, что она содержит в основном достижимые объекты, весь регион может быть логически перенесен в старое поколение без копирования каких-либо объектов и может быть выделен новый питомник (или неполный старый питомник может быть переработан).

1 голос
/ 10 марта 2009

Эмм ... причина моего профессора - сделать нашу жизнь (его учеников) тяжелее и научить нас "реальному". Ха-ха:)

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

0 голосов
/ 07 мая 2015

Сборка мусора против утечек

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

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

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

Комплексное управление ресурсами

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

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

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

Без сборки мусора, если одному из них не удастся это сделать (возможно, у него / нее был плохой день, он является одним из менее опытных разработчиков, находился в затруднительном положении из-за сжатых сроков с проигравшим) тестирование и проверка стандартов, независимо от причины), остается висящий указатель / дескриптор / ссылка . Доступ к нему будет сбой приложение с segfault. Отслеживание такого segfault с помощью отладчика часто сразу показывает, где и почему это произошло.

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

Сбой или не сбой

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

Так что, если вы работаете над таким проектом, где сразу очевидный и исправимый сбой во время тестирования может быть действительно предпочтительнее негерметичного программного обеспечения, которое часто вылетает под радар тестирования с такими ошибками, сбор мусора, если он не сочетается с очень осторожным Стандарты кодирования и осведомленность каждого члена команды о том, как следить за его ошибками (например, необходимость в слабых или фантомных ссылках), может принести больше вреда, чем пользы. На мой взгляд, сборка мусора лучше всего работает с гораздо меньшими, более тесными командами и проектами с фактически более высоким , не более низким уровнем знаний в области управления состоянием / ресурсами, или теми, где такие утечки ресурсов не так уж и плохи. как сбой.

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

0 голосов
/ 09 ноября 2014

Один из возможных ответов: «Там, где безопасность / стабильность системы не является основным требованием».

Имейте в виду, что приложения, имеющие свободное управление над памятью, могут вызывать всевозможные проблемы с безопасностью, в том числе просто выделять и не освобождать память (DoS-атака из-за замедления работы системы из-за недостатка доступного ресурса памяти). Например, это основная часть модели безопасности Java - ее GC гарантирует, что этого никогда не произойдет.

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

0 голосов
/ 10 марта 2009

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

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

0 голосов
/ 10 марта 2009

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

...