Эффективность .NET сборщика мусора - PullRequest
12 голосов
/ 26 апреля 2010

Хорошо, вот сделка. Некоторые люди отдают свои жизни в руки сборщику мусора в .NET, а некоторые просто не доверяют ему.

Я один из тех, кто частично доверяет ему, если он не очень критичен к производительности (я знаю, я знаю, что критичен к производительности + .net не самая удачная комбинация), и в этом случае я предпочитаю избавляться от своих объектов вручную и ресурсы.

Я спрашиваю, есть ли какие-либо факты относительно того, насколько эффективен или неэффективен сборщик мусора на самом деле?

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

Спасибо

Редактировать: Чтобы уточнить, я в основном говорю: независимо от того, какое приложение мы пишем, критично ли оно к ресурсам или нет, мы можем просто забыть обо всем и позволить GC справиться с этим или нет?

Я пытаюсь получить ответ на самом деле о том, что GC делает и не делает, и где он может потерпеть неудачу, где ручное управление памятью будет успешным, ЕСЛИ существуют такие сценарии. Есть ли у него ОГРАНИЧЕНИЯ? Я не знаю, как я мог бы объяснить свой вопрос дальше.

У меня нет проблем с приложением, это теоретический вопрос.

Ответы [ 5 ]

9 голосов
/ 26 апреля 2010

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

Хотя GC выполняется довольно быстро, это займет время, чтобы выполнить, и, следовательно, сборка мусора в вашем непрерывный режим работы может ввести как нежелательную задержку, так и изменение латентности в тех приложения, которые очень чувствителен к задержке. Как иллюстрация, если вы обрабатываете 100 000 сообщений в секунду и каждое сообщение использует небольшой временный 2 строка символов, около 8 байт (это функция строкового кодирования и реализация строкового объекта) выделяется для каждого сообщения. таким образом вы создаете почти 1 МБ мусора в секунду. Для системы, которая может необходимо обеспечить постоянную производительность в течение 16 часов это означает, что вам придется убирать 16 часов х 60 минут x 60 секунд x 1 МБ Память примерно 56 ГБ памяти. Лучшее, что вы можете ожидать от сборщик мусора в том что будет очистить это полностью в любом Поколение 0 или 1 коллекции и вызывает дрожание, самое худшее, что это вызовет мусор поколения 2 Коллекция со связанным большим всплеск задержки.

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

5 голосов
/ 02 ноября 2011

Я могу рассказать вам о некоторых проблемах, которые у меня были с сборщиком мусора в .NET.

Если вы запускаете приложение, использующее GC сервера (например, приложение ASP.NET), тогда ваша задержка будет действительно ужасна , с паузами около секунды, когда ни один из ваших потоков не может сделать любой прогресс вообще. Это связано с тем, что сервер .NET 4 GC - это глобальный сборщик мусора. По-видимому, в .NET 4.5 будет представлен первый по большей части параллельный сервер Microsoft GC.

Однажды я написал некоторый инструментальный код для измерения задержек в параллельной системе, используя встроенные коллекции, такие как ConcurrentBag, и продолжал исчерпывать память в 32-битной среде из-за большой фрагментации кучи, потому что .NET GC не выполняет дефрагментацию большого размера. объекты. Мне пришлось заменить основанные на массиве структуры данных чисто функциональными структурами данных, которые разбросаны на миллионы крошечных кусочков, чтобы избежать попадания чего-либо в кучу больших объектов (LOH), вызывающего фрагментацию.

Я обнаружил ошибки в ГХ, такие как этот , из-за которого ГХ теряет память до тех пор, пока не будет исчерпана вся системная память, после чего куча очищается в одном огромном цикле ГХ, который останавливает не только все ваши потоки, но даже другие процессы (потому что система пошла на перестановку) в течение нескольких минут!

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

Однако .NET GC, как правило, очень хорош, и при осторожном использовании можно получить хорошие результаты. Например, я недавно написал отказоустойчивый сервер, который обеспечивает задержку от двери до двери в среднем 114 мкс с 95% задержек ниже 0,5 мс. Это впечатляюще близко к современному состоянию (см. здесь и здесь ), учитывая, что я сам написал всю платформу на F # всего за несколько месяцев. Сеть фактически способствовала увеличению задержки, чем .NET GC.

3 голосов
/ 26 апреля 2010

Вам не нужно беспокоиться об этом.

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

И вы вряд ли найдете такие крайние случаи. Это действительно работает удивительно хорошо. Если вы имели опыт использования распределителей кучи только в типичных реализациях C и C ++, .NET GC - совершенно другое животное. Я был так поражен этим Я написал этот пост в блоге, чтобы попытаться объяснить суть .

2 голосов
/ 27 апреля 2010

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

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

GC в текущих реализациях .NET не в режиме реального времени; они эвристически эффективны и быстры. Обратите внимание, что то же самое можно сказать и о ручном выделении с malloc() в C (или new в C ++), поэтому, если вам нужны гарантии в реальном времени, вам уже нужно использовать что-то особенное. Если нет, то я не хочу, чтобы вы разрабатывали встроенную электронику для автомобилей и самолетов, которыми я пользуюсь!

1 голос
/ 26 апреля 2010

Любой алгоритм GC будет благоприятствовать определенной деятельности (т. Е. Оптимизации). Вам придется проверить GC на соответствие вашему шаблону использования, чтобы увидеть, насколько он эффективен для вас. Даже если кто-то еще изучит конкретное поведение .net GC и выдаст «факты» и «цифры», ваши результаты могут сильно отличаться.

Я думаю, что единственный разумный ответ на этот вопрос - анекдотичный. У большинства людей нет проблем с эффективностью ГХ даже в крупных ситуациях. Это считается, по крайней мере, эффективным или более эффективным, чем GC других управляемых языков. Если вы все еще обеспокоены, вам, вероятно, не следует использовать управляемый язык.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...