Задержка коллекции мусора .NET

Я профилирую память в приложении С#, используя профилировщик памяти, dotTrace и счетчики perfmon. Единственный вопрос, на который я не смог ответить: Какова максимальная латентность, вызванная сбором мусора в моем приложении? Я могу получить приблизительное значение для этого, используя% времени в коллекции Garbage, но есть ли способ сделать отдельные коллекции?

Ответ 1

Похоже, вы задаете 2 вопроса 1- Существует ли максимальная латентность для GC? 2 Как сделать сборку отдельных GC?

Для # 1 пропускная способность GC составляет примерно 200 МБ/с/куча. Это означает, что GC может собрать кучу размером 100 МБ за 1 секунду. Понятие перехвата связано с тем, что сервер GC, так как мы создаем 1 кучку на процессор.

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

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

Для # 2: у нас очень мощная трассировка в .net-инфраструктуре под названием ETW (она доступна в Windows, и мы используем ее в CLR). ETW означает Трассировка событий для Windows (. Мы запускаем события ETW, когда собирается начать GC, и когда GC заканчивается с использованием этих событий ETW, вы можете рассчитать время, проведенное в каждом GC.

Для получения дополнительной информации вы можете обратиться к CLR ETW reference. Кроме того, для хорошей управляемой библиотеки, которая позволяет вам работать с событиями ETW, проверьте TraceEvent

Надеюсь на эту помощь. Благодаря

Ответ 2

Возможно генерировать коллекции gen # 2 (медленные) с помощью метода GC.RegisterForFullGCNotification(). Тем не менее для этого требуется версия сервера коллектора (<gcserver> в файле .config).

Классический Гейзенбергиан, он побеждает точку, поскольку только версия рабочей станции поддерживает параллельные коллекции # 2, они могут значительно улучшить латентность. Фактическая латентность, которую он производит, очень непредсказуема, она сильно зависит от того, на какой скорости потоки в вашей программе распределяются и заполняются gen # 0 и # 1, пока выполняется параллельная коллекция. Не рекомендуется задавать этот вопрос.

Ответ 3

Я не думаю, что существует "максимальная латентность". GC загорается, когда это необходимо - при наличии давления в памяти. То же самое приложение, запущенное на машине с 2 ГБ, будет видеть более частые коллекции, чем одно и то же приложение на машине 4 ГБ.

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

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

EDIT: zneak делает замечательный комментарий - я, возможно, неправильно понял ваш вопрос.

Время, проведенное в GC, также зависит от множества факторов, какое поколение собирается? Gen0 очень быстрые. Gen1 занимает больше времени, а Gen2 - дольше. Благодаря хорошему использованию памяти я ищу 10 коллекций Gen1 для каждого Gen2 и 10 Gen0 для каждого Gen1. В течение дня на нашем сильно используемом веб-сайте я могу увидеть 10 000 Gen0, 1000 Gen1 и 100 Gen2. YMMV.