2013-05-21 2 views
2

Я собирал счетчики производительности для управляемого приложения примерно за четыре дня. За это время были следующие коллекции мусора:(Почти) все коллекции мусора полные коллекции

  • Поколение 0: 133.695
  • Поколение 1: 133.413
  • Generation 2: 133.254

Некоторые из них "индуцированные" полный коллекции с использованием GC.Collect(). За четыре дня было 323 человека.

Почему все (или, по сути, все) мои коллекции будут полными коллекциями? Я предполагаю, что это обстоятельство способствует очень высокому счетчику «% времени в ГК» (выше 70%, даже когда значительно сокращается байт/сек).

Может быть, а может и не важно отметить, что я запускаю .NET 4.0, 64-разрядную версию и используя GC сервера в файле конфигурации.

+2

Мы должны были бы узнать больше о вашем приложении, чтобы даже угадать, я думаю. – Joel

+2

Если вы вызываете GC.Collect, вы не можете вообще рассуждать о том, как часто выполняется каждая коллекция; вы возитесь с тем, что он хочет сделать. Кроме того, GC очень динамичен в том, что он запускает коллекции, когда он думает, что это необходимо, что означает, что это будет * очень * зависит от кода, который вы используете, от того, сколько памяти вы создаете, в какой области, как долго вы держите на него и т. д. – Servy

+2

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

ответ

6

Я выделение больших объемов памяти (свыше 300 Мбайт/с в разы)

Этого достаточно, чтобы объяснить, что вы наблюдаете. Это вызовет множество коллекций в течение этой секунды, кучи gen # 0 и gen # 1 не такие большие. С очень высокой вероятностью, что объекты в этих поколениях все еще используются, поскольку они были просто выделены, поэтому коллекции gen # 0 и 1 не занимают достаточно места и почти каждый объект получает повышение до 2-го поколения. GC имеет контрмеры для этого, он автоматически вырастет размеры поколений. Но это не может идти в ногу с голодным голодом за память. Вы можете использовать счетчики производительности памяти .NET в Perfmon.exe, чтобы наблюдать это. Любой профилировщик .NET-памяти даст вам представление о более красивых графиках.

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

+0

Мои продвинутые байты/сек от gen 0 до gen 1 составляют всего около 32K, это не кажется очень высоким. Мои продвинутые байты/сек от генератора 1 до 2-го поколения составляют чуть менее 4K. Это тоже не очень высоко. Я запускаю сервер GC, который, насколько я понимаю, дает мне значительно большие кучи? – Mark

+0

@Mark, вы выделяете массивы или объекты размером более 85 000 байт? Если это так, то вы обходите обычную схему распределения и попадаете в то, что называется [Большая куча объектов] (http://msdn.microsoft.com/en-us/magazine/cc534993.aspx), что является особым куча, которая исправлена, но никогда не уплотняется. Это может быть причиной того, что вы не видите рекламных акций, которые вы ожидаете от поколения к поколению. Я думаю, что Ганс прямо на месте в том, что сборщик мусора должен облагаться налогом, чтобы не отставать от такого высокого спроса на память. =) –

+0

@sgorozco: Видимо, я. Используя PerfView, я взял данные для GC, и почти каждая коллекция (792 из 795) была из-за AllocLarge. – Mark