Да, это звучит чрезмерно. Уменьшение количества GC, вероятно, было бы единственным лучшим шагом, который вы могли бы предпринять для сокращения времени выполнения вашего приложения (если это ваша цель).
Высокий «% времени в GC» обычно вызывается выделением, а затем выбрасыванием тысяч или миллионов объектов. Хороший способ узнать, что происходит, - использовать инструмент профилирования памяти.
Microsoft предоставляет бесплатный CLR Profiler . Это покажет вам каждое выделение, но заставит ваше приложение работать в 10-60 раз медленнее. Вам может потребоваться запустить его на меньшем количестве входных данных, чтобы он мог завершить анализ за разумное время.
Отличным коммерческим инструментом является SciTech .NET Memory Profiler . Это накладывает гораздо меньше времени на выполнение, и доступна бесплатная пробная версия. Делая несколько снимков во время работы вашего процесса, вы можете узнать, какие типы объектов часто выделяются (а затем уничтожаются).
После того, как вы определили источник распределения, вам необходимо изучить код и выяснить, как можно сократить эти распределения. Несмотря на то, что не существует ответов «один размер подходит всем», некоторые вещи, с которыми я сталкивался в прошлом, включают:
- String.Split может создавать сотни небольших недолговечных строк. Если вы выполняете много манипуляций со строками, это может помочь обработать строку, пройдя ее символ за символом.
- Создание массивов или списков из тысяч небольших классов (скажем, размером менее 24 байт) может быть дорогим; если эти классы можно рассматривать как типы значений, это может (иногда) значительно улучшить вещи, превратив их в структуры.
- Создание тысяч маленьких массивов может значительно увеличить использование памяти (поскольку каждый массив имеет небольшое количество служебных данных); иногда их можно заменить одним большим массивом и индексами в его подразделе.
- Наличие большого количества финализируемых объектов (особенно если они не утилизируются) может оказать большое давление на сборщик мусора; убедитесь, что вы правильно утилизируете все IDisposable объекты, и обратите внимание, что ваши собственные типы не должны (почти) никогда не иметь финализаторы .
- У Microsoft есть статья с Рекомендациями по сборке мусора для улучшения производительности.