Разделение кучи при использовании байтовых массивов
У меня есть приложение С# 4.0 (один производитель/один потребитель), который передает огромное количество данных в куски. Хотя никакого нового выделения памяти у меня нет, через некоторое время закончится память.
Я профилировал память, используя профайлер памяти Redgate, и там есть много свободной памяти. Он говорит, что свободная память не может использоваться из-за фрагментации.
Я использую блокирующую коллекцию в качестве массива буфера и байта как члены:
BlockingCollection<byte[]> segments = new BlockingCollection<byte[]>(8);
// producer:
segments.Add(buffer);
// consumer:
byte[] buffer = _segments.Take();
Как избежать фрагментации управляемой памяти?
Ответы
Ответ 1
Вероятно, вы столкнулись с проблемой кучи больших объектов - объекты размером более 85 000 байт помещаются в кучу большого объекта, которая не уплотняется, что может привести к странным ситуациям с памятью. Хотя, по-видимому, производительность в .NET 4 была улучшена, она далека от совершенства. Решение состоит в том, чтобы в основном использовать собственный пул буферов, который содержит несколько статически распределенных блоков памяти и повторное использование этих файлов.
В этом вопросе есть целая куча вопросов.
Обновление. Microsoft предоставляет диспетчер буфера как часть стека WCF. Существует также один в кодепроекте.
Ответ 2
Как долго ваш массив byte []? Они попадают в маленький предмет или кучу больших объектов? Если вы испытываете фрагментацию памяти, я бы сказал, что они попадают в LOH.
Поэтому вы должны повторно использовать одни и те же байт-массивы (использовать пул) или использовать более мелкие куски. LOH никогда не уплотняется, поэтому он может стать довольно фрагментированным. К сожалению, этого не происходит. (Не зная этого ограничения и избегая его)